Hi Rich I apply this patch, and test virsh attach-device/detach-device. As a result, libvirt has no problem about attaching and detaching disk/insterface. But, because option flag of <file> in virsh attach-device/detach-device is wrong, I correct it. > Euch, add 'close (fd);' in there ... > And, 'close (fd);' is added to this patch. Thanks, Masayuki Sunou In message <4652FB40.3060700@xxxxxxxxxx> "Re: [PATCH] Device attach/detach on virsh(XML version)" ""Richard W.M. Jones" <rjones@xxxxxxxxxx>" wrote: > Richard W.M. Jones wrote: > > + buffer = realloc (buffer, len+1); > > + if (buffer == NULL) goto out_of_memory; > > + buffer[len] = '\0'; > > + return buffer; > > Euch, add 'close (fd);' in there ... > > Rich. > > -- > Emerging Technologies, Red Hat - http://et.redhat.com/~rjones/ > Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod > Street, Windsor, Berkshire, SL4 1TE, United Kingdom. Registered in > England and Wales under Company Registration No. 03798903 > ------------------------------------------------------------------------------- Index: src/virsh.c =================================================================== RCS file: /data/cvs/libvirt/src/virsh.c,v retrieving revision 1.75 diff -u -p -r1.75 virsh.c --- src/virsh.c 3 May 2007 16:03:02 -0000 1.75 +++ src/virsh.c 23 May 2007 05:04:56 -0000 @@ -22,6 +22,7 @@ #include <string.h> #include <stdarg.h> #include <unistd.h> +#include <errno.h> #include <getopt.h> #include <sys/types.h> #include <sys/time.h> @@ -673,6 +674,49 @@ static vshCmdOptDef opts_create[] = { {NULL, 0, 0, NULL} }; +/* Read in a whole file and return it as a string. + * If it fails, it logs an error and returns NULL. + * String must be freed by caller. + */ +static char * +readFile (vshControl *ctl, const char *filename) +{ + char *buffer = NULL, *oldbuffer; + int len = 0, fd, r; + char b[1024]; + + fd = open (filename, O_RDONLY); + if (fd == -1) { + file_error: + vshError (ctl, FALSE, "%s: %s", filename, strerror (errno)); + error: + if (buffer) free (buffer); + if (fd >= 0) close (fd); + return NULL; + } + + for (;;) { + r = read (fd, b, sizeof b); + if (r == -1) goto file_error; + if (r == 0) break; /* End of file. */ + oldbuffer = buffer; + buffer = realloc (buffer, len+r); + if (buffer == NULL) { + out_of_memory: + vshError (ctl, FALSE, "realloc: %s", strerror (errno)); + goto error; + } + memcpy (buffer+len, b, r); + len += r; + } + + buffer = realloc (buffer, len+1); + if (buffer == NULL) goto out_of_memory; + buffer[len] = '\0'; + close (fd); + return buffer; +} + static int cmdCreate(vshControl * ctl, vshCmd * cmd) { @@ -680,8 +724,7 @@ cmdCreate(vshControl * ctl, vshCmd * cmd char *from; int found; int ret = TRUE; - char buffer[BUFSIZ]; - int fd, l; + char *buffer; if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; @@ -690,19 +733,12 @@ cmdCreate(vshControl * ctl, vshCmd * cmd if (!found) return FALSE; - fd = open(from, O_RDONLY); - if (fd < 0) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - return(FALSE); - } - l = read(fd, &buffer[0], sizeof(buffer)); - if ((l <= 0) || (l >= (int) sizeof(buffer))) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - close(fd); - return(FALSE); - } - buffer[l] = 0; - dom = virDomainCreateLinux(ctl->conn, &buffer[0], 0); + buffer = readFile (ctl, from); + if (buffer == NULL) return FALSE; + + dom = virDomainCreateLinux(ctl->conn, buffer, 0); + free (buffer); + if (dom != NULL) { vshPrint(ctl, _("Domain %s created from %s\n"), virDomainGetName(dom), from); @@ -735,8 +771,7 @@ cmdDefine(vshControl * ctl, vshCmd * cmd char *from; int found; int ret = TRUE; - char buffer[BUFSIZ]; - int fd, l; + char *buffer; if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; @@ -745,19 +780,12 @@ cmdDefine(vshControl * ctl, vshCmd * cmd if (!found) return FALSE; - fd = open(from, O_RDONLY); - if (fd < 0) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - return(FALSE); - } - l = read(fd, &buffer[0], sizeof(buffer)); - if ((l <= 0) || (l >= (int) sizeof(buffer))) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - close(fd); - return(FALSE); - } - buffer[l] = 0; - dom = virDomainDefineXML(ctl->conn, &buffer[0]); + buffer = readFile (ctl, from); + if (buffer == NULL) return FALSE; + + dom = virDomainDefineXML(ctl->conn, buffer); + free (buffer); + if (dom != NULL) { vshPrint(ctl, _("Domain %s defined from %s\n"), virDomainGetName(dom), from); @@ -1800,8 +1828,7 @@ cmdNetworkCreate(vshControl * ctl, vshCm char *from; int found; int ret = TRUE; - char buffer[BUFSIZ]; - int fd, l; + char *buffer; if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; @@ -1810,19 +1837,12 @@ cmdNetworkCreate(vshControl * ctl, vshCm if (!found) return FALSE; - fd = open(from, O_RDONLY); - if (fd < 0) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - return(FALSE); - } - l = read(fd, &buffer[0], sizeof(buffer)); - if ((l <= 0) || (l >= (int) sizeof(buffer))) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - close(fd); - return(FALSE); - } - buffer[l] = 0; - network = virNetworkCreateXML(ctl->conn, &buffer[0]); + buffer = readFile (ctl, from); + if (buffer == NULL) return FALSE; + + network = virNetworkCreateXML(ctl->conn, buffer); + free (buffer); + if (network != NULL) { vshPrint(ctl, _("Network %s created from %s\n"), virNetworkGetName(network), from); @@ -1856,8 +1876,7 @@ cmdNetworkDefine(vshControl * ctl, vshCm char *from; int found; int ret = TRUE; - char buffer[BUFSIZ]; - int fd, l; + char *buffer; if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; @@ -1866,19 +1885,12 @@ cmdNetworkDefine(vshControl * ctl, vshCm if (!found) return FALSE; - fd = open(from, O_RDONLY); - if (fd < 0) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - return(FALSE); - } - l = read(fd, &buffer[0], sizeof(buffer)); - if ((l <= 0) || (l >= (int) sizeof(buffer))) { - vshError(ctl, FALSE, _("Failed to read description file %s"), from); - close(fd); - return(FALSE); - } - buffer[l] = 0; - network = virNetworkDefineXML(ctl->conn, &buffer[0]); + buffer = readFile (ctl, from); + if (buffer == NULL) return FALSE; + + network = virNetworkDefineXML(ctl->conn, buffer); + free (buffer); + if (network != NULL) { vshPrint(ctl, _("Network %s defined from %s\n"), virNetworkGetName(network), from); @@ -2403,6 +2415,113 @@ cmdVNCDisplay(vshControl * ctl, vshCmd * return ret; } +/* + * "attach-device" command + */ +static vshCmdInfo info_attach_device[] = { + {"syntax", "attach-device <domain> <file> "}, + {"help", gettext_noop("attach device from an XML file")}, + {"desc", gettext_noop("Attach device from an XML <file>.")}, + {NULL, NULL} +}; + +static vshCmdOptDef opts_attach_device[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, + {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("XML file")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdAttachDevice(vshControl * ctl, vshCmd * cmd) +{ + virDomainPtr dom; + char *from; + char *buffer; + int ret = TRUE; + int found; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL))) + return FALSE; + + from = vshCommandOptString(cmd, "file", &found); + if (!found) { + virDomainFree(dom); + return FALSE; + } + + buffer = readFile (ctl, from); + if (buffer == NULL) return FALSE; + + ret = virDomainAttachDevice(dom, buffer); + free (buffer); + + if (ret < 0) { + vshError(ctl, FALSE, _("Failed to attach device from %s"), from); + virDomainFree(dom); + return FALSE; + } + + virDomainFree(dom); + return TRUE; +} + + +/* + * "detach-device" command + */ +static vshCmdInfo info_detach_device[] = { + {"syntax", "detach-device <domain> <file> "}, + {"help", gettext_noop("detach device from an XML file")}, + {"desc", gettext_noop("Detach device from an XML <file>")}, + {NULL, NULL} +}; + +static vshCmdOptDef opts_detach_device[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, + {"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("XML file")}, + {NULL, 0, 0, NULL} +}; + +static int +cmdDetachDevice(vshControl * ctl, vshCmd * cmd) +{ + virDomainPtr dom; + char *from; + char *buffer; + int ret = TRUE; + int found; + + if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) + return FALSE; + + if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL))) + return FALSE; + + from = vshCommandOptString(cmd, "file", &found); + if (!found) { + virDomainFree(dom); + return FALSE; + } + + buffer = readFile (ctl, from); + if (buffer == NULL) return FALSE; + + ret = virDomainDetachDevice(dom, buffer); + free (buffer); + + if (ret < 0) { + vshError(ctl, FALSE, _("Failed to detach device from %s"), from); + virDomainFree(dom); + return FALSE; + } + + virDomainFree(dom); + return TRUE; +} + /* * "quit" command @@ -2467,6 +2586,8 @@ static vshCmdDef commands[] = { {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin}, {"version", cmdVersion, NULL, info_version}, {"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay}, + {"attach-device", cmdAttachDevice, opts_attach_device, info_attach_device}, + {"detach-device", cmdDetachDevice, opts_detach_device, info_detach_device}, {NULL, NULL, NULL, NULL} }; -------------------------------------------------------------------------------