X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fvirt.c;h=a95b0290037a4b83f6ecf094ffdf4565323bed4e;hb=99ec97dcdfaf242ba0683a230ba51e4a87f7458b;hp=cd48888687a6251197f30f7d81b0f233184dfbb9;hpb=a4c28b4ed1c5a102c8de2a7425568eb504d05c34;p=libguestfs.git diff --git a/src/virt.c b/src/virt.c index cd48888..a95b029 100644 --- a/src/virt.c +++ b/src/virt.c @@ -67,6 +67,8 @@ struct guestfs___add_libvirt_dom_argv { const char *iface; #define GUESTFS___ADD_LIBVIRT_DOM_LIVE_BITMASK (UINT64_C(1)<<2) int live; +#define GUESTFS___ADD_LIBVIRT_DOM_READONLYDISK_BITMASK (UINT64_C(1)<<3) + const char *readonlydisk; }; static int guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, const struct guestfs___add_libvirt_dom_argv *optargs); @@ -82,6 +84,8 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, const char *libvirturi; int readonly; int live; + int allowuuid; + const char *readonlydisk; const char *iface; struct guestfs___add_libvirt_dom_argv optargs2 = { .bitmask = 0 }; @@ -93,6 +97,10 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, ? optargs->iface : NULL; live = optargs->bitmask & GUESTFS_ADD_DOMAIN_LIVE_BITMASK ? optargs->live : 0; + allowuuid = optargs->bitmask & GUESTFS_ADD_DOMAIN_ALLOWUUID_BITMASK + ? optargs->allowuuid : 0; + readonlydisk = optargs->bitmask & GUESTFS_ADD_DOMAIN_READONLYDISK_BITMASK + ? optargs->readonlydisk : NULL; if (live && readonly) { error (g, _("you cannot set both live and readonly flags")); @@ -114,7 +122,14 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, */ virConnSetErrorFunc (conn, NULL, ignore_errors); - dom = virDomainLookupByName (conn, domain_name); + /* Try UUID first. */ + if (allowuuid) + dom = virDomainLookupByUUIDString (conn, domain_name); + + /* Try ordinary domain name. */ + if (!dom) + dom = virDomainLookupByName (conn, domain_name); + if (!dom) { err = virGetLastError (); error (g, _("no libvirt domain called '%s': %s"), @@ -134,6 +149,10 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name, optargs2.bitmask |= GUESTFS___ADD_LIBVIRT_DOM_LIVE_BITMASK; optargs2.live = live; } + if (readonlydisk) { + optargs2.bitmask |= GUESTFS___ADD_LIBVIRT_DOM_READONLYDISK_BITMASK; + optargs2.readonlydisk = readonlydisk; + } r = guestfs___add_libvirt_dom (g, dom, &optargs2); @@ -157,6 +176,7 @@ guestfs___for_each_disk (guestfs_h *g, virDomainPtr dom, int (*f) (guestfs_h *g, const char *filename, const char *format, + int readonly, void *data), void *data) { @@ -274,9 +294,20 @@ guestfs___for_each_disk (guestfs_h *g, format = (char *) xmlNodeListGetString (doc, attr->children, 1); } + /* Get the flag. */ + xmlXPathObjectPtr xpreadonly; + + xpathCtx->node = nodes->nodeTab[i]; + xpreadonly = xmlXPathEvalExpression (BAD_CAST "./readonly", xpathCtx); + int readonly = 0; + if (xpreadonly != NULL && + xpreadonly->nodesetval && + xpreadonly->nodesetval->nodeNr > 0) + readonly = 1; + int t; if (f) - t = f (g, filename, format, data); + t = f (g, filename, format, readonly, data); else t = 0; @@ -284,6 +315,7 @@ guestfs___for_each_disk (guestfs_h *g, xmlFree (format); xmlXPathFreeObject (xpfilename); xmlXPathFreeObject (xpformat); + xmlXPathFreeObject (xpreadonly); if (t == -1) goto cleanup; @@ -310,9 +342,23 @@ guestfs___for_each_disk (guestfs_h *g, /* This was proposed as an external API, but it's not quite baked yet. */ -static int add_disk (guestfs_h *g, const char *filename, const char *format, void *optargs_vp); +static int add_disk (guestfs_h *g, const char *filename, const char *format, int readonly, void *data); static int connect_live (guestfs_h *g, virDomainPtr dom); +enum readonlydisk { + readonlydisk_error, + readonlydisk_read, + readonlydisk_write, + readonlydisk_ignore, +}; + +struct add_disk_data { + int readonly; + enum readonlydisk readonlydisk; + /* Other args to pass through to add_drive_opts. */ + struct guestfs_add_drive_opts_argv optargs; +}; + static int guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, const struct guestfs___add_libvirt_dom_argv *optargs) @@ -322,6 +368,8 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, int readonly; const char *iface; int live; + /* Default for back-compat reasons: */ + enum readonlydisk readonlydisk = readonlydisk_write; readonly = optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_READONLY_BITMASK @@ -333,6 +381,21 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_LIVE_BITMASK ? optargs->live : 0; + if ((optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_READONLYDISK_BITMASK)) { + if (STREQ (optargs->readonlydisk, "error")) + readonlydisk = readonlydisk_error; + else if (STREQ (optargs->readonlydisk, "read")) + readonlydisk = readonlydisk_read; + else if (STREQ (optargs->readonlydisk, "write")) + readonlydisk = readonlydisk_write; + else if (STREQ (optargs->readonlydisk, "ignore")) + readonlydisk = readonlydisk_ignore; + else { + error (g, _("unknown readonlydisk parameter")); + return -1; + } + } + if (live && readonly) { error (g, _("you cannot set both live and readonly flags")); return -1; @@ -369,40 +432,75 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom, } /* Add the disks. */ - struct guestfs_add_drive_opts_argv optargs2 = { .bitmask = 0 }; - if (readonly) { - optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK; - optargs2.readonly = readonly; - } + struct add_disk_data data; + data.optargs.bitmask = 0; + data.readonly = readonly; + data.readonlydisk = readonlydisk; if (iface) { - optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_IFACE_BITMASK; - optargs2.iface = iface; + data.optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_IFACE_BITMASK; + data.optargs.iface = iface; } /* Checkpoint the command line around the operation so that either * all disks are added or none are added. */ - cmdline_pos = guestfs___checkpoint_cmdline (g); - r = guestfs___for_each_disk (g, dom, add_disk, &optargs2); + struct drive **cp = guestfs___checkpoint_drives (g); + r = guestfs___for_each_disk (g, dom, add_disk, &data); if (r == -1) - guestfs___rollback_cmdline (g, cmdline_pos); + guestfs___rollback_drives (g, cp); return r; } static int -add_disk (guestfs_h *g, const char *filename, const char *format, - void *optargs_vp) +add_disk (guestfs_h *g, + const char *filename, const char *format, int readonly_in_xml, + void *datavp) { - struct guestfs_add_drive_opts_argv *optargs = optargs_vp; + struct add_disk_data *data = datavp; + /* Copy whole struct so we can make local changes: */ + struct guestfs_add_drive_opts_argv optargs = data->optargs; + int readonly, error = 0, skip = 0; + + if (readonly_in_xml) { /* appears in the XML */ + if (data->readonly) { /* asked to add disk read-only */ + switch (data->readonlydisk) { + case readonlydisk_error: readonly = 1; break; + case readonlydisk_read: readonly = 1; break; + case readonlydisk_write: readonly = 1; break; + case readonlydisk_ignore: skip = 1; break; + default: abort (); + } + } else { /* asked to add disk for read/write */ + switch (data->readonlydisk) { + case readonlydisk_error: error = 1; break; + case readonlydisk_read: readonly = 1; break; + case readonlydisk_write: readonly = 0; break; + case readonlydisk_ignore: skip = 1; break; + default: abort (); + } + } + } else /* no in XML */ + readonly = data->readonly; + + if (skip) + return 0; + + if (error) { + error (g, _("%s: disk is marked in libvirt XML, and readonlydisk was set to \"error\""), + filename); + return -1; + } + + optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK; + optargs.readonly = readonly; if (format) { - optargs->bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; - optargs->format = format; - } else - optargs->bitmask &= ~GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; + optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; + optargs.format = format; + } - return guestfs__add_drive_opts (g, filename, optargs); + return guestfs__add_drive_opts (g, filename, &optargs); } static int