Re: [libvirt] Re: OpenVZ : The restriction of domain name should be addressed
Thanks, Chris and Daniel I corrected the code that I posted here according to your comments. Chris, I now need to handle openvz containers by character(name) not integer(id) at all. diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 54bcaa9..3b8505d 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -156,12 +156,13 @@ openvzDomainDefineCmd(virConnectPtr conn, fclose(fp); if (max_veid == 0) { -max_veid = 100; +/* OpenVZ reserves the IDs ranging from 0 to 100 */ +max_veid = 101; } else { max_veid++; } -sprintf(str_id, %d, max_veid++); +snprintf(str_id, sizeof(str_id), %d, max_veid); ADD_ARG_LIT(str_id); ADD_ARG_LIT(--name); -- 1.5.2.2 - Yuji Nishida nish...@nict.go.jp On 2009/09/23, at 23:45, Daniel Veillard wrote: On Wed, Sep 23, 2009 at 10:22:51AM +0200, Chris Lalancette wrote: Yuji NISHIDA wrote: Hi Daniel Fixed patch according to your comments in openvzDomainDefineCmd func. --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -101,6 +101,9 @@ static int openvzDomainDefineCmd(virConnectPtr conn, virDomainDefPtr vmdef) { int narg; +int veid; +int max_veid; +FILE *fp; for (narg = 0; narg maxarg; narg++) args[narg] = NULL; @@ -130,6 +133,38 @@ static int openvzDomainDefineCmd(virConnectPtr conn, ADD_ARG_LIT(VZCTL); ADD_ARG_LIT(--quiet); ADD_ARG_LIT(create); + +if ((fp = popen(VZLIST -a -ovpsid -H 2/dev/null, r)) == NULL) { +openvzError(NULL, VIR_ERR_INTERNAL_ERROR, %s, _(popen failed)); +return -1; +} +max_veid = 0; +while(!feof(fp)) { +if (fscanf(fp, %d\n, veid ) != 1) { +if (feof(fp)) +break; + +openvzError(NULL, VIR_ERR_INTERNAL_ERROR, +%s, _(Failed to parse vzlist output)); +goto cleanup; +} +if(veid max_veid){ +max_veid = veid; +} +} +fclose(fp); + +if(max_veid == 0){ +max_veid = 100; +}else{ +max_veid++; +} You might want to add a comment saying that vpsid's below 100 are reserved for OpenVZ internal use; otherwise, it looks like an odd place to begin numbering. good point. + +char str_id[10]; +sprintf( str_id, %d, max_veid++ ); You'll want to use snprintf here, like: snprintf(str_id, sizeof(str_id), %d, max_veid++); (bear with me on this part, since I don't know much about OpenVZ). Besides that, though, I'm not sure you necessarily want to do it like this, since you aren't really tracking the ID's properly. The problem I see is that if you do it like this, start the container, and then do virsh dumpxml openvz, you won't see the ID in the output XML, like you do for the other drivers. Is that intentional? If not, I think you'll want to store the id in the virDomainDef-id member so that the information will be properly printed to the user. I actually applied that patch on monday (after a couple of cleanups) and apparently my reply mail is part of the set that got lost :-( Author: Yuji NISHIDA nish...@nict.go.jp 2009-09-22 12:19:09 Committer: Daniel Veillard veill...@redhat.com 2009-09-22 12:19:09 0c85095e46f3aba09ac401f559b76df0b0bea998 the snprintf wasn't looking critical because I don't think a %d can generate more than 9 characters, but you're right in the absolute :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Miscellaneous fixes to build with -Werror
Charles Duffy wrote: HACKING suggests compiling with --enable-compile-warnings=error before submitting any patches; however, current master fails for me on this account (CentOS 5.3; gcc 4.1.2). Please see attached. I suspect most of these should be uncontroversial -- but wonder if perhaps virStrcpy uses would be better converted to virStrcpyStatic rather than adding virStrcpy to the symbol list as done That's not possible in general. The problem with virStrcpyStatic is that it *has* to be a macro, and not only that, the users *have* to know that sizeof(src) returns something meaningful. Some callers do not, and cannot, provide for that, so those callsites have to use virStrcpy. I think adding it to the symbol table will have to suffice, although I'm curious about warnings themselves (since I compiled on RHEL-5.4 yesterday, and don't remember seeing any warnings at all). Can you post the warnings that you are seeing? -- Chris Lalancette -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix a typo in virDiskHasValidPciAddr()
Jiri Denemark wrote: Signed-off-by: Jiri Denemark jdene...@redhat.com --- src/conf/domain_conf.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 09368d9..d494e54 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -125,7 +125,7 @@ struct _virDomainDiskDef { static inline int virDiskHasValidPciAddr(virDomainDiskDefPtr def) { -return def-pci_addr.domain || def-pci_addr.domain || def-pci_addr.slot; +return def-pci_addr.domain || def-pci_addr.bus || def-pci_addr.slot; } Eek, good catch. ACK -- Chris Lalancette -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Miscellaneous fixes to build with -Werror
Chris Lalancette wrote: Charles Duffy wrote: HACKING suggests compiling with --enable-compile-warnings=error before submitting any patches; however, current master fails for me on this account (CentOS 5.3; gcc 4.1.2). Please see attached. I suspect most of these should be uncontroversial -- but wonder if perhaps virStrcpy uses would be better converted to virStrcpyStatic rather than adding virStrcpy to the symbol list as done That's not possible in general. The problem with virStrcpyStatic is that it *has* to be a macro, and not only that, the users *have* to know that sizeof(src) returns something meaningful. Some callers do not, and cannot, provide for that, so those callsites have to use virStrcpy. I think adding it to the symbol table will have to suffice, although I'm curious about warnings themselves (since I compiled on RHEL-5.4 yesterday, and don't remember seeing any warnings at all). Can you post the warnings that you are seeing? Actually, I take this (partially) back. I had forgotten to add on the --enable-compile-warnings=error, so I missed the warnings in the sea of output. So all of your fixes except for the virStrcpy() one I saw, and in point of fact those are all real bugs. (The log_level fix in qemudSetLogging() does also seem right; it's possible that we don't set the var_name in GET_CONF_INT if we don't find it in the config file, so initializing it to 0 seems to be the right thing to do). I didn't see the error about the virStrcpy one, so I would still be curious as to what you are seeing there. -- Chris Lalancette -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Miscellaneous fixes to build with -Werror
Interesting that gcc-4.41 isn't giving me any warnings On Wed, 2009-09-23 at 12:32 -0500, Charles Duffy wrote: diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index af215ca..25d983e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6132,7 +6132,7 @@ static int qemudDomainDetachHostPciDevice(virConnectPtr conn, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { -virDomainHostdevDefPtr detach; +virDomainHostdevDefPtr detach = NULL; char *cmd, *reply; int i, ret; pciDevice *pci; Looks like a very real bug, so I just went ahead and pused this one Thanks, Mark. -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix a typo in virDiskHasValidPciAddr()
On Wed, 2009-09-23 at 18:46 +0200, Jiri Denemark wrote: Signed-off-by: Jiri Denemark jdene...@redhat.com --- src/conf/domain_conf.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 09368d9..d494e54 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -125,7 +125,7 @@ struct _virDomainDiskDef { static inline int virDiskHasValidPciAddr(virDomainDiskDefPtr def) { -return def-pci_addr.domain || def-pci_addr.domain || def-pci_addr.slot; +return def-pci_addr.domain || def-pci_addr.bus || def-pci_addr.slot; } Nice catch, I've pushed this and the same fix for virNetHasValidPciAddr() Thanks, Mark. -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] qemu_driver migrateuri handling broken?
On Wed, Sep 23, 2009 at 10:05:36AM +0200, Chris Lalancette wrote: We are working on a new tunnelled migration scheme that will be uniform across drivers. ic - To be honest, I was confused by the migrateuri anyhow, since I considered the situation where libvirt traffic is tunneled via SSH, but Xen-/KVM-/foo communication may be direct a rather rare exception (or am I mistaken?) (I understood that this was the rationale behind the hostname-Query in the first place) Well, the rationale is that you may have two paths to get to a machine, and you may only want to allow migration traffic on one of them (say, a direct cross-over) since the data goes across unencrypted. So you might have a machine with eth0 and eth1, where eth0 is exposed to the world, and you have libvirtd listening on eth0. But then when you actually do the migration, you want it to send the data across on eth1. Note also that libvirt traffic tunnelled via ssh isn't the only method, you can also attach to libvirtd via TLS and TCP (with SASL encryption). Hm - I acknowledge that there might be such situation, so you want to have this feature. And as long as there's a way around the assumption that the remote hostname - especially without a domain part - is resolvable at the sending side, my only concern would be a unified migrateuri syntax, which seems to be on the way :) . I guess my actual confusion is rather about the choice of the default behaviour, than the feature's existence (since I never had the split-path-situation in this context, but definitely had an environment where `hostname` output would not be resolvable, and I deemed the latter more probable than the prior) - but that's certainly debatable. the part doesn't do much besides setting the port - the hostname is even ignored ;) ... and the error comes from the receiving side - not the sending one. Therefore as far as I see, the only thing broken is that now the sending side can't choose the listening port number on the receiving side (is this a debugging feature?) Not exactly a debugging feature, more a give more control to the admin. If you do not supply a migrateuri, then libvirtd will choose a port between 49152 and 49216. However, if you don't want to open up all of those ports on your firewall, you can specify a migrateuri to say use *this* port, and then you only have to open up one port in the firewall. So we do need to allow the migrateuri, and removing it isn't really feasible. Again acknowledged, but then I would request a possibility to specify the IP, while leaving the port choice up to the receiving side (basically making the port specification optional rather than mandatory). My rationale for the request would be that when you consider scripted (i.e. automated) management of virtual nodes along with the possibility of several concurrent migrations, the port choice on the sending side is likely to turn out awkward, even though you may have an environment without DNS, or with dual-homing (and therefore need to specify the migrateuri). The tunnelled migration stuff should make this a bit easier, although we'll still have to allow the migrateuri type stuff for the dual-homed situation. Hm - I don't know what exactly you have in mind (not familiar with the plans). But I'd like to bring forward the point that as a user I was quite confused, because I intuitively expected a different default behaviour than the one libvirt currently exhibits (i.e., I was not prepared to get a 'hostname could not be resolved' type of error, when I specified an IP as migration destination ;) ). Cheers, Gregor. -- Chris Lalancette -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/9] Clarify documentation for private symbols
On Fri, Sep 18, 2009 at 05:26:08PM +0200, Wolfgang Mauerer wrote: The instruction See Makefile.am in libvirt.private_syms always makes me think that this file is autogenerated and should not be touched manually. This patch spares every reader of libvirt.private_syms the hassle of reading Makefile.am before augmenting libvirt.private_syms. Signed-off-by: Wolfgang Mauerer wolfgang.maue...@siemens.com Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- src/libvirt_private.syms |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 867678f..f724493 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1,5 +1,6 @@ # -# General private symbols. See Makefile.am. +# General private symbols. Add symbols here, and see Makefile.am for +# more details. # ACK, this is fine Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/9] Extend disk element with controller information
On Fri, Sep 18, 2009 at 05:26:09PM +0200, Wolfgang Mauerer wrote: This allows us to connect a disk with a specific controller, which is required for disk hotadd/remove. A new XML child element is added to the disk container: disk ... controller pci_addr=addr id=identifier bus=number unit=number/ /disk Either id _or_ pci_addr can be specified. When the controller has been brought into the system via tghe hotplug mechanism also included in this patch series, it will typically have an ID. In other cases, the controller can also be specified with the PCI address. I think it would be desriable to make 'id' the mandatory argument and not use 'pci_addr' in this area of the XML. controller id=identifier bus=number unit=number/ If fact I think it'd be good to rename 'id' to 'name' since in libvirt context we typically use 'id' to be be positive integer identifier. 'name' reflects the fact that this device idenifier is really a string. Outside the scope of your patches, I think it would be worth adding a 'name' attribute to all devices in the libvirt XML as a standardized unique identifier. We already have to keep track of a 'name' internally for NIC hotplug with QEMU, and with QEMU's qdev work we're going to end up having to track a 'name' for pretty much all devices. Thus we might as well expose it in the XML memmove(target, target+6, strlen(target)-5); +} else if ((controller == NULL) + (xmlStrEqual(cur-name, BAD_CAST controller))) { + controller_id = virXMLPropString(cur, id); + bus_id = virXMLPropString(cur, bus); + unit_id = virXMLPropString(cur, unit); } else if ((driverName == NULL) (xmlStrEqual(cur-name, BAD_CAST driver))) { driverName = virXMLPropString(cur, name); @@ -800,6 +811,24 @@ virDomainDiskDefParseXML(virConnectPtr conn, } } +if (controller) { +def-controller_id = controller_id; + + def-bus_id = -1; + if (bus_id virStrToLong_i(bus_id, NULL, 10, def-bus_id) 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, %s, + _(Cannot parse controller 'bus' attribute)); + goto error; + } + + def-unit_id = -1; + if (unit_id virStrToLong_i(unit_id, NULL, 10, def-unit_id) 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, %s, + _(Cannot parse controller 'unit' attribute)); + goto error; + } +} + There's a few whitespace issues here - I guess some tabs crept into the patch Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/9] Add new domain device: controller
On Fri, Sep 18, 2009 at 05:26:10PM +0200, Wolfgang Mauerer wrote: This augments virDomainDevice with a controller element that is used to represent disk controllers (e.g., scsi controllers). The XML format is given by controller type=scsi id=my_id bus addr=Domain:Bus:Slot /controller where type denotes the disk interface (scsi, ide,...), id is an arbitrary string that identifies the controller for disk hotadd/remove, and bus addr denotes the controller address on the PCI bus. The bus element can be omitted; in this case, an address will be assigned automatically. Currently, only hotplugging scsi controllers on a PCI bus is supported, and this only for qemu guests As mentioned in the previous patch, I reckon 'id' is better called 'name'. For PCI addresses, it is desirable to fully normalize the XML format, by which I mean have separate attributes for domain, bus and slot. We already have a syntax for PCI addresses used for host device passthrough, so it'd make sense to use the same syntax here for controllers. More broadly, we're probably going to have to add a PCI address element to all our devices. While it is unlikely we'll need non-PCI addresses, it doesn't hurt to make it explicit by adding a type='pci' attribute Thus I'd suggest address type='pci' domain='0x' bus='0x06' slot='0x12'/ Instead of bus addr=Domain:Bus:Slot In the domain_conf.c/.h parser, we could have a datatype like enum { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; typedef struct _virDomainDevicePCIAddress virDomainDevicePCIAddress; struct _virDomainDevicePCIAddress { unsigned domain; unsigned bus; unsigned slot; unsigned function; }; typedef struct _virDomainDeviceAddress virDomainDeviceAddress; struct _virDomainDeviceAddress { int type; union { virDomainDevicePCIAddress pci; } data; }; Which we then use in all the places in domain_conf.h wanting address information. Obviously we'd not use the 'function' field in most places, but doesn't hurt to have it. And a pair of methods for parsing/formatting this address info we can call from all the appropriate locations. diff --git a/src/domain_conf.h b/src/domain_conf.h index 898f6c9..6b3cb09 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -111,6 +111,11 @@ struct _virDomainDiskDef { char *src; char *dst; char *controller_id; +struct { +unsigned domain; +unsigned bus; +unsigned slot; +} controller_pci_addr; I think we should stick to just using the controller name as the mandatory identifier for cross-referencing disks to controllers. char *driverName; char *driverType; char *serial; @@ -125,6 +130,19 @@ struct _virDomainDiskDef { virStorageEncryptionPtr encryption; }; +/* Stores the virtual disk controller configuration */ +typedef struct _virDomainControllerDef virDomainControllerDef; +typedef virDomainControllerDef *virDomainControllerDefPtr; +struct _virDomainControllerDef { +int type; +char *id; +struct { +unsigned domain; +unsigned bus; +unsigned slot; +} pci_addr; +}; With the generic address data type and s/id/name/, this would be just struct _virDomainControllerDef { int type; char *name; virDomainDeviceAddress addr; }; Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 5/9] Implement controller hotplugging
On Fri, Sep 18, 2009 at 05:26:12PM +0200, Wolfgang Mauerer wrote: This enables to hot-add disk controllers without attached disks into the system. Previously, it was only possible to (implicitly) add disk controllers in the static machine configuration. Notice that the actual functionality is only available for qemu at present, but other emulators can be extended likewise. Any idea what we can do about initial startup? eg, if we start a guest with 1 SCSI controller and 1 disk, and then we've then hotplugged a 2nd controller, and 1 disk. When we later boot or migrate the same guest, we need to have suitable QEMU command line args to make sure we get 2 controllers each with the same disk, rather than 1 controller with 2 disks. I'm not sure how we do this in QEMU, hopefully the existing args support it in some way I've not realized, or failing that the new qdev -device args might help us. Signed-off-by: Wolfgang Mauerer wolfgang.maue...@siemens.com Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- src/domain_conf.c| 26 +++--- src/domain_conf.h|2 ++ src/libvirt_private.syms |1 + src/qemu_driver.c| 21 + 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/domain_conf.c b/src/domain_conf.c index d0fda64..ea51fda 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -647,7 +647,6 @@ void virDomainRemoveInactive(virDomainObjListPtr doms, } - /* Parse the XML definition for a disk * @param node XML nodeset to parse for disk definition */ @@ -2554,6 +2553,27 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn, #endif +static int virDomainControllerCompare(virDomainControllerDefPtr a, + virDomainControllerDefPtr b) { +if (a-pci_addr.bus == b-pci_addr.bus) { +if (a-pci_addr.domain == b-pci_addr.domain) +return a-pci_addr.slot - b-pci_addr.slot; + +return a-pci_addr.domain - b-pci_addr.domain; +} + +return a-pci_addr.bus - b-pci_addr.bus; +} + + +int virDomainControllerQSort(const void *a, const void *b) +{ +const virDomainControllerDefPtr *da = a; +const virDomainControllerDefPtr *db = b; + +return virDomainControllerCompare(*da, *db); +} + I know we used todo this for disk devices, but I'd recommand not going a qsort of devices when hotplugging/unplugging. For hotplug always append to the list, for unplug just shuffle down later devices in the list to fill the hole. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 7/9] Remove surprises in the semantics of disk-hotadd
On Fri, Sep 18, 2009 at 05:26:14PM +0200, Wolfgang Mauerer wrote: When a disk is added without an explicitly specified controller as host, then try to find the first available controller. If none exists, do not (as in previous versions) add a new PCI controller device with the disk attached, but bail out with an error. Notice that this patch changes the behaviour as compared to older libvirt releases, as has been discussed on the mailing list (see http://thread.gmane.org/gmane.comp.emulators.libvirt/15860) Yes, I still think is the good way to go Daniel Signed-off-by: Wolfgang Mauerer wolfgang.maue...@siemens.com Signed-off-by: Jan Kiszka jan.kis...@siemens.com --- src/qemu_driver.c | 172 ++--- 1 files changed, 85 insertions(+), 87 deletions(-) diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 990f05a..f1c2a45 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -5417,68 +5417,81 @@ try_command: controller_specified = 1; } -if (controller_specified) { -if (dev-data.disk-controller_id) { -for (i = 0 ; i vm-def-ncontrollers ; i++) { -if (STREQ(dev-data.disk-controller_id, - vm-def-controllers[i]-id)) { -break; -} -} - -if (i == vm-def-ncontrollers) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(Controller does not exist)); -return -1; -} +if (!controller_specified) { +/* Find an appropriate controller for disk-hotadd. Notice that + the admissible controller types (SCSI, virtio) have already + been checked in qemudDomainAttachDevice. */ +for (i = 0 ; i vm-def-ncontrollers ; i++) { +if (vm-def-controllers[i]-type == dev-data.disk-type) +break; +} + +if (i == vm-def-ncontrollers) { +qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _(Cannot find appropriate controller for hot-add)); +return -1; +} -domain = vm-def-controllers[i]-pci_addr.domain; -bus= vm-def-controllers[i]-pci_addr.bus; -slot = vm-def-controllers[i]-pci_addr.slot; -} else { -domain = dev-data.disk-controller_pci_addr.domain; -bus= dev-data.disk-controller_pci_addr.bus; -slot = dev-data.disk-controller_pci_addr.slot; - -for (i = 0 ; i vm-def-ncontrollers ; i++) { -if (domain == vm-def-controllers[i]-pci_addr.domain -bus== vm-def-controllers[i]-pci_addr.bus -slot == vm-def-controllers[i]-pci_addr.slot) -break; -} +domain = vm-def-controllers[i]-pci_addr.domain; +bus= vm-def-controllers[i]-pci_addr.bus; +slot = vm-def-controllers[i]-pci_addr.slot; +} -if (i == vm-def-ncontrollers) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(Controller does not exist)); -return -1; +if (controller_specified dev-data.disk-controller_id) { +for (i = 0 ; i vm-def-ncontrollers ; i++) { +if (STREQ(dev-data.disk-controller_id, + vm-def-controllers[i]-id)) { +break; } - } - -if (dev-data.disk-bus_id != -1) { -virBufferVSprintf(buf, ,bus=%d, dev-data.disk-bus_id); } -if (dev-data.disk-unit_id != -1) { -virBufferVSprintf(buf, ,unit=%d, dev-data.disk-unit_id); +if (i == vm-def-ncontrollers) { +qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _(Controller does not exist)); +return -1; +} + +domain = vm-def-controllers[i]-pci_addr.domain; +bus= vm-def-controllers[i]-pci_addr.bus; +slot = vm-def-controllers[i]-pci_addr.slot; +} else if (controller_specified) { +domain = dev-data.disk-controller_pci_addr.domain; +bus= dev-data.disk-controller_pci_addr.bus; +slot = dev-data.disk-controller_pci_addr.slot; + +for (i = 0 ; i vm-def-ncontrollers ; i++) { +if (domain == vm-def-controllers[i]-pci_addr.domain +bus== vm-def-controllers[i]-pci_addr.bus +slot == vm-def-controllers[i]-pci_addr.slot) +break; } + +if (i == vm-def-ncontrollers) { +qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _(Controller does not exist)); +
Re: [libvirt] Miscellaneous fixes to build with -Werror
Charles Duffy wrote: HACKING suggests compiling with --enable-compile-warnings=error before submitting any patches; however, current master fails for me on this account (CentOS 5.3; gcc 4.1.2). Please see attached. I suspect most of these should be uncontroversial -- but wonder if perhaps virStrcpy uses would be better converted to virStrcpyStatic rather than adding virStrcpy to the symbol list as done here, and am curious about whether the need for explicit initialization to silence a warning regarding qemudSetLogging's log_level indicates a bug in the macro later used to assign that value. diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 2bae782..ec2eab1 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -2492,7 +2492,7 @@ remoteReadSaslAllowedUsernameList (virConfPtr conf ATTRIBUTE_UNUSED, */ static int qemudSetLogging(virConfPtr conf, const char *filename) { -int log_level; +int log_level = 0; char *log_filters = NULL; char *log_outputs = NULL; int ret = -1; Looking at this more, I'm not sure. The comment above GET_CONF_INT(log_level) looks to be bogus; GET_CONF_INT does *not* return 0 if the value is not in the config file, it doesn't change anything at all. Still, I don't quite know the reasoning behind the original change (back in early August), so I'm uncomfortable changing it. diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index af215ca..25d983e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6132,7 +6132,7 @@ static int qemudDomainDetachHostPciDevice(virConnectPtr conn, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { -virDomainHostdevDefPtr detach; +virDomainHostdevDefPtr detach = NULL; char *cmd, *reply; int i, ret; pciDevice *pci; Mark McLoughlin pushed this one. diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index 20a3fa8..9c4102e 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -432,7 +432,7 @@ static virSecretEntryPtr secretLoad(virConnectPtr conn, virSecretDriverStatePtr driver, const char *xml_basename) { -virSecretDefPtr def; +virSecretDefPtr def = NULL; virSecretEntryPtr secret = NULL, ret = NULL; char *xml_filename; I just pushed this one because it's an obvious bugfix. -- Chris Lalancette -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 21/27] Add API for issuing 'getfd' and 'closefd' monitor commands
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorCloseFileHandle and qemuMonitorSendFileHandle APIs for processing file handles * src/qemu/qemu_driver.c: Convert NIC hotplug method over to use qemuMonitorCloseFileHandle and qemuMonitorSendFileHandle --- src/qemu/qemu_driver.c | 40 +++-- src/qemu/qemu_monitor_text.c | 78 ++ src/qemu/qemu_monitor_text.h |6 +++ 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b447a87..f8710a6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4619,7 +4619,7 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, { virDomainNetDefPtr net = dev-data.net; char *cmd = NULL, *reply = NULL, *remove_cmd = NULL; -char *tapfd_name = NULL, *tapfd_close = NULL; +char *tapfd_name = NULL; int i, tapfd = -1; unsigned domain, bus, slot; @@ -4662,32 +4662,8 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, if (virAsprintf(tapfd_name, fd-%s, net-hostnet_name) 0) goto no_memory; -if (virAsprintf(tapfd_close, closefd %s, tapfd_name) 0) -goto no_memory; - -if (virAsprintf(cmd, getfd %s, tapfd_name) 0) -goto no_memory; - -if (qemudMonitorCommandWithFd(vm, cmd, tapfd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(failed to pass fd to qemu with '%s'), cmd); +if (qemuMonitorSendFileHandle(vm, tapfd_name, tapfd) 0) goto cleanup; -} - -DEBUG(%s: getfd reply: %s, vm-def-name, reply); - -/* If the command isn't supported then qemu prints: - * unknown command: getfd */ -if (strstr(reply, unknown command:)) { -qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, - %s, - _(bridge/network interface attach not supported: - qemu 'getfd' monitor command not available)); -goto cleanup; -} - -VIR_FREE(reply); -VIR_FREE(cmd); } if (qemuBuildHostNetStr(conn, net, host_net_add , ' ', @@ -4713,7 +4689,6 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, VIR_FREE(reply); VIR_FREE(cmd); VIR_FREE(tapfd_name); -VIR_FREE(tapfd_close); if (tapfd != -1) close(tapfd); tapfd = -1; @@ -4760,12 +4735,10 @@ try_remove: try_tapfd_close: VIR_FREE(reply); -if (tapfd_close) { -if (qemudMonitorCommand(vm, tapfd_close, reply) 0) -VIR_WARN(_(Failed to close tapfd with '%s'\n), tapfd_close); -else -VIR_DEBUG(%s: closefd: %s\n, vm-def-name, reply); -} +if (tapfd_name +qemuMonitorCloseFileHandle(vm, tapfd_name) 0) +VIR_WARN(_(Failed to close tapfd with '%s'\n), tapfd_name); + goto cleanup; no_memory: @@ -4774,7 +4747,6 @@ cleanup: VIR_FREE(cmd); VIR_FREE(reply); VIR_FREE(remove_cmd); -VIR_FREE(tapfd_close); VIR_FREE(tapfd_name); if (tapfd != -1) close(tapfd); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 765a482..92a2dbd 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1551,3 +1551,81 @@ cleanup: VIR_FREE(reply); return ret; } + + +int qemuMonitorSendFileHandle(const virDomainObjPtr vm, + const char *fdname, + int fd) +{ +char *cmd; +char *reply = NULL; +int ret = -1; + +if (virAsprintf(cmd, getfd %s, fdname) 0) { +virReportOOMError(NULL); +return -1; +} + +if (qemudMonitorCommandWithFd(vm, cmd, fd, reply) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _(failed to pass fd to qemu with '%s'), cmd); +goto cleanup; +} + +DEBUG(%s: getfd reply: %s, vm-def-name, reply); + +/* If the command isn't supported then qemu prints: + * unknown command: getfd */ +if (strstr(reply, unknown command:)) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_SUPPORT, + _(qemu does not support sending of file handles: %s), + reply); +goto cleanup; +} + +ret = 0; + +cleanup: +VIR_FREE(cmd); +VIR_FREE(reply); +return ret; +} + + +int qemuMonitorCloseFileHandle(const virDomainObjPtr vm, + const char *fdname) +{ +char *cmd; +char *reply = NULL; +int ret = -1; + +if (virAsprintf(cmd, closefd %s, fdname) 0) { +virReportOOMError(NULL); +return -1; +} + +if (qemudMonitorCommand(vm, cmd, reply) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _(failed to
[libvirt] [PATCH 05/27] Add API for 'stop' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add a new qemuMonitorStopCPUs() API * src/qemu/qemu_driver.c: Replace direct monitor commands for 'stop' with qemuMonitorStopCPUs() --- src/qemu/qemu_driver.c | 28 src/qemu/qemu_monitor_text.c | 13 + src/qemu/qemu_monitor_text.h |1 + 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1717cbd..5ebd4b7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2749,7 +2749,6 @@ cleanup: static int qemudDomainSuspend(virDomainPtr dom) { struct qemud_driver *driver = dom-conn-privateData; -char *info; virDomainObjPtr vm; int ret = -1; virDomainEventPtr event = NULL; @@ -2770,17 +2769,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { goto cleanup; } if (vm-state != VIR_DOMAIN_PAUSED) { -if (qemudMonitorCommand(vm, stop, info) 0) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(suspend operation failed)); +if (qemuMonitorStopCPUs(vm) 0) goto cleanup; -} vm-state = VIR_DOMAIN_PAUSED; -qemudDebug(Reply %s, info); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); -VIR_FREE(info); } if (virDomainSaveStatus(dom-conn, driver-stateDir, vm) 0) goto cleanup; @@ -3365,13 +3359,9 @@ static int qemudDomainSave(virDomainPtr dom, /* Pause */ if (vm-state == VIR_DOMAIN_RUNNING) { header.was_running = 1; -if (qemudMonitorCommand(vm, stop, info) 0) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(suspend operation failed)); +if (qemuMonitorStopCPUs(vm) 0) goto cleanup; -} vm-state = VIR_DOMAIN_PAUSED; -qemudDebug(Reply %s, info); VIR_FREE(info); } @@ -3527,13 +3517,8 @@ static int qemudDomainCoreDump(virDomainPtr dom, /* Pause domain for non-live dump */ if (vm-state == VIR_DOMAIN_RUNNING) { -if (qemudMonitorCommand (vm, stop, info) 0) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(suspending before dump failed)); +if (qemuMonitorStopCPUs(vm) 0) goto cleanup; -} -DEBUG (%s: stop reply: %s, vm-def-name, info); -VIR_FREE(info); paused = 1; } @@ -6747,13 +6732,8 @@ qemudDomainMigratePerform (virDomainPtr dom, if (!(flags VIR_MIGRATE_LIVE)) { /* Pause domain for non-live migration */ -if (qemudMonitorCommand (vm, stop, info) 0) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(off-line migration specified, but suspend operation failed)); +if (qemuMonitorStopCPUs(vm) 0) goto cleanup; -} -DEBUG (%s: stop reply: %s, vm-def-name, info); -VIR_FREE(info); paused = 1; event = virDomainEventNewFromObj(vm, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 3c12073..ec30e72 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -438,6 +438,19 @@ qemuMonitorStartCPUs(virConnectPtr conn, } +int +qemuMonitorStopCPUs(const virDomainObjPtr vm) { +char *info; + +if (qemudMonitorCommand(vm, stop, info) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(cannot stop CPU execution)); +return -1; +} +VIR_FREE(info); +return 0; +} + int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, int **pids) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 2632ecf..eb1ba44 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -67,6 +67,7 @@ int qemudMonitorCommandExtra(const virDomainObjPtr vm, int qemuMonitorStartCPUs(virConnectPtr conn, const virDomainObjPtr vm); +int qemuMonitorStopCPUs(const virDomainObjPtr vm); int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, int **pids); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 25/27] Remove low level monitor APIs from header file
* src/qemu/qemu_monitor.h: Remove qemudMonitorCommand, qemudMonitorCommandWithFd, qemudMonitorCommandWithHandler, qemudMonitorCommandExtra low level APIs * src/qemu/qemu_monitor.c: Replace s/qemud/qemuMonitor/ --- src/qemu/qemu_monitor_text.c | 166 ++ src/qemu/qemu_monitor_text.h | 33 2 files changed, 88 insertions(+), 111 deletions(-) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 0675bf5..2c41288 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -41,7 +41,17 @@ #define VIR_FROM_THIS VIR_FROM_QEMU -static char *qemudEscape(const char *in, int shell) +#define QEMU_CMD_PROMPT \n(qemu) +#define QEMU_PASSWD_PROMPT Password: + +/* Return -1 for error, 0 for success */ +typedef int qemuMonitorExtraPromptHandler(const virDomainObjPtr vm, + const char *buf, + const char *prompt, + void *data); + + +static char *qemuMonitorEscape(const char *in, int shell) { int len = 0; int i, j; @@ -113,14 +123,14 @@ static char *qemudEscape(const char *in, int shell) return out; } -static char *qemudEscapeMonitorArg(const char *in) +static char *qemuMonitorEscapeArg(const char *in) { -return qemudEscape(in, 0); +return qemuMonitorEscape(in, 0); } -static char *qemudEscapeShellArg(const char *in) +static char *qemuMonitorEscapeShell(const char *in) { -return qemudEscape(in, 1); +return qemuMonitorEscape(in, 1); } /* Throw away any data available on the monitor @@ -144,10 +154,10 @@ qemuMonitorDiscardPendingData(virDomainObjPtr vm) { } static int -qemudMonitorSendUnix(const virDomainObjPtr vm, - const char *cmd, - size_t cmdlen, - int scm_fd) +qemuMonitorSendUnix(const virDomainObjPtr vm, +const char *cmd, +size_t cmdlen, +int scm_fd) { struct msghdr msg; struct iovec iov[1]; @@ -183,9 +193,9 @@ qemudMonitorSendUnix(const virDomainObjPtr vm, } static int -qemudMonitorSend(const virDomainObjPtr vm, - const char *cmd, - int scm_fd) +qemuMonitorSend(const virDomainObjPtr vm, +const char *cmd, +int scm_fd) { char *full; size_t len; @@ -198,7 +208,7 @@ qemudMonitorSend(const virDomainObjPtr vm, switch (vm-monitor_chr-type) { case VIR_DOMAIN_CHR_TYPE_UNIX: -if (qemudMonitorSendUnix(vm, full, len, scm_fd) 0) +if (qemuMonitorSendUnix(vm, full, len, scm_fd) 0) goto out; break; default: @@ -214,14 +224,14 @@ out: return ret; } -int -qemudMonitorCommandWithHandler(const virDomainObjPtr vm, - const char *cmd, - const char *extraPrompt, - qemudMonitorExtraPromptHandler extraHandler, - void *handlerData, - int scm_fd, - char **reply) { +static int +qemuMonitorCommandWithHandler(const virDomainObjPtr vm, + const char *cmd, + const char *extraPrompt, + qemuMonitorExtraPromptHandler extraHandler, + void *handlerData, + int scm_fd, + char **reply) { int size = 0; char *buf = NULL; @@ -233,7 +243,7 @@ qemudMonitorCommandWithHandler(const virDomainObjPtr vm, qemuMonitorDiscardPendingData(vm); VIR_DEBUG(Send '%s', cmd); -if (qemudMonitorSend(vm, cmd, scm_fd) 0) +if (qemuMonitorSend(vm, cmd, scm_fd) 0) return -1; *reply = NULL; @@ -324,23 +334,23 @@ struct extraHandlerData }; static int -qemudMonitorCommandSimpleExtraHandler(const virDomainObjPtr vm, - const char *buf ATTRIBUTE_UNUSED, - const char *prompt ATTRIBUTE_UNUSED, - void *data_) +qemuMonitorCommandSimpleExtraHandler(const virDomainObjPtr vm, + const char *buf ATTRIBUTE_UNUSED, + const char *prompt ATTRIBUTE_UNUSED, + void *data_) { struct extraHandlerData *data = data_; if (!data-first) return 0; -if (qemudMonitorSend(vm, data-reply, -1) 0) +if (qemuMonitorSend(vm, data-reply, -1) 0) return -1; data-first = false; return 0; } -int -qemudMonitorCommandExtra(const virDomainObjPtr vm, +static int +qemuMonitorCommandExtra(const virDomainObjPtr vm, const char *cmd, const char *extra,
[libvirt] [PATCH 17/27] Add APIs for sending 'usb_add' command for host devices
One API adds an exact device based on bus+dev, the other adds any device matching vendor+product * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorAddUSBDeviceExact() and qemuMonitorAddUSBDeviceMatch() commands. * src/qemu/qemu_driver.c: Switch over to using the new qemuMonitorAddUSBDeviceExact() and qemuMonitorAddUSBDeviceMatch() --- src/qemu/qemu_driver.c | 43 +--- src/qemu/qemu_monitor_text.c | 73 ++ src/qemu/qemu_monitor_text.h |7 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 635fb84..f33c24e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4984,7 +4984,6 @@ static int qemudDomainAttachHostUsbDevice(virConnectPtr conn, virDomainDeviceDefPtr dev) { int ret; -char *cmd, *reply; if (VIR_REALLOC_N(vm-def-hostdevs, vm-def-nhostdevs+1) 0) { virReportOOMError(conn); @@ -4992,43 +4991,19 @@ static int qemudDomainAttachHostUsbDevice(virConnectPtr conn, } if (dev-data.hostdev-source.subsys.u.usb.vendor) { -ret = virAsprintf(cmd, usb_add host:%.4x:%.4x, - dev-data.hostdev-source.subsys.u.usb.vendor, - dev-data.hostdev-source.subsys.u.usb.product); +ret = qemuMonitorAddUSBDeviceMatch(vm, + dev-data.hostdev-source.subsys.u.usb.vendor, + dev-data.hostdev-source.subsys.u.usb.product); } else { -ret = virAsprintf(cmd, usb_add host:%.3d.%.3d, - dev-data.hostdev-source.subsys.u.usb.bus, - dev-data.hostdev-source.subsys.u.usb.device); -} -if (ret == -1) { -virReportOOMError(conn); -return -1; -} - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(cannot attach usb device)); -VIR_FREE(cmd); -return -1; +ret = qemuMonitorAddUSBDeviceExact(vm, + dev-data.hostdev-source.subsys.u.usb.bus, + dev-data.hostdev-source.subsys.u.usb.device); } -DEBUG (%s: attach_usb reply: %s, vm-def-name, reply); -/* If the command failed qemu prints: - * Could not add ... */ -if (strstr(reply, Could not add )) { -qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, - _(adding usb device failed)); -VIR_FREE(reply); -VIR_FREE(cmd); -return -1; -} - -vm-def-hostdevs[vm-def-nhostdevs++] = dev-data.hostdev; +if (ret != -1) +vm-def-hostdevs[vm-def-nhostdevs++] = dev-data.hostdev; -VIR_FREE(reply); -VIR_FREE(cmd); -return 0; +return ret; } static int qemudDomainAttachHostDevice(virConnectPtr conn, diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index fd50cf2..0e0334c 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1242,3 +1242,76 @@ cleanup: VIR_FREE(safepath); return ret; } + + +static int qemuMonitorAddUSBDevice(const virDomainObjPtr vm, + const char *addr) +{ +char *cmd; +char *reply = NULL; +int ret = -1; + +if (virAsprintf(cmd, usb_add %s, addr) 0) { +virReportOOMError(NULL); +return -1; +} + +if (qemudMonitorCommand(vm, cmd, reply) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(cannot attach usb device)); +goto cleanup; +} + +DEBUG (%s: attach_usb reply: %s, vm-def-name, reply); +/* If the command failed qemu prints: + * Could not add ... */ +if (strstr(reply, Could not add )) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(adding usb device failed)); +goto cleanup; +} + +ret = 0; + +cleanup: +VIR_FREE(cmd); +VIR_FREE(reply); +return ret; +} + + +int qemuMonitorAddUSBDeviceExact(const virDomainObjPtr vm, + int bus, + int dev) +{ +int ret; +char *addr; + +if (virAsprintf(addr, host:%.3d.%.3d, bus, dev) 0) { +virReportOOMError(NULL); +return -1; +} + +ret = qemuMonitorAddUSBDevice(vm, addr); + +VIR_FREE(addr); +return ret; +} + +int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm, + int vendor, + int product) +{ +int ret; +char *addr; + +if (virAsprintf(addr, host:%.4x:%.4x, vendor, product) 0) { +virReportOOMError(NULL); +return -1; +} + +
[libvirt] [PATCH 15/27] Add API for issugin 'migrate' command with exec protocol
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorMigrateToCommand() API * src/qemu/qemu_driver.c: Switch over to using the qemuMonitorMigrateToCommand() API for core dumps and save to file APIs --- src/libvirt_private.syms |1 + src/qemu/qemu_driver.c | 119 -- src/qemu/qemu_monitor_text.c | 63 +-- src/qemu/qemu_monitor_text.h |4 ++ 4 files changed, 86 insertions(+), 101 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a6668f3..f8598c7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -453,6 +453,7 @@ virGetGroupID; virFileFindMountPoint; virFileWaitForDevices; virFileMatchesNameSuffix; +virArgvToString; # usb.h diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f234639..da08af9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3170,11 +3170,6 @@ static char *qemudEscapeMonitorArg(const char *in) return qemudEscape(in, 0); } -static char *qemudEscapeShellArg(const char *in) -{ -return qemudEscape(in, 1); -} - #define QEMUD_SAVE_MAGIC LibvirtQemudSave #define QEMUD_SAVE_VERSION 2 @@ -3217,15 +3212,11 @@ static int qemudDomainSave(virDomainPtr dom, { struct qemud_driver *driver = dom-conn-privateData; virDomainObjPtr vm = NULL; -char *command = NULL; -char *info = NULL; int fd = -1; -char *safe_path = NULL; char *xml = NULL; struct qemud_save_header header; int ret = -1; virDomainEventPtr event = NULL; -int internalret; memset(header, 0, sizeof(header)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); @@ -3267,7 +3258,6 @@ static int qemudDomainSave(virDomainPtr dom, if (qemuMonitorStopCPUs(vm) 0) goto cleanup; vm-state = VIR_DOMAIN_PAUSED; -VIR_FREE(info); } /* Get XML for the domain */ @@ -3306,55 +3296,21 @@ static int qemudDomainSave(virDomainPtr dom, } fd = -1; -/* Migrate to file */ -safe_path = qemudEscapeShellArg(path); -if (!safe_path) { -virReportOOMError(dom-conn); -goto cleanup; -} - -{ +if (header.compressed == QEMUD_SAVE_FORMAT_RAW) { +const char *args[] = { cat, NULL }; +ret = qemuMonitorMigrateToCommand(vm, args, path); +} else { const char *prog = qemudSaveCompressionTypeToString(header.compressed); -const char *args; - -if (prog == NULL) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _(Invalid compress format %d), header.compressed); -goto cleanup; -} - -if (STREQ (prog, raw)) { -prog = cat; -args = ; -} else { -args = -c; -} -internalret = virAsprintf(command, migrate \exec: - %s %s '%s' 2/dev/null\, prog, args, - safe_path); -} - -if (internalret 0) { -virReportOOMError(dom-conn); -goto cleanup; -} - -if (qemudMonitorCommand(vm, command, info) 0) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(migrate operation failed)); -goto cleanup; +const char *args[] = { +prog, +-c, +NULL +}; +ret = qemuMonitorMigrateToCommand(vm, args, path); } -DEBUG (%s: migrate reply: %s, vm-def-name, info); - -/* If the command isn't supported then qemu prints: - * unknown command: migrate */ -if (strstr(info, unknown command:)) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_NO_SUPPORT, - %s, - _('migrate' not supported by this qemu)); +if (ret 0) goto cleanup; -} /* Shut it down */ qemudShutdownVMDaemon(dom-conn, driver, vm); @@ -3366,15 +3322,11 @@ static int qemudDomainSave(virDomainPtr dom, vm); vm = NULL; } -ret = 0; cleanup: if (fd != -1) close(fd); VIR_FREE(xml); -VIR_FREE(safe_path); -VIR_FREE(command); -VIR_FREE(info); if (ret != 0) unlink(path); if (vm) @@ -3391,11 +3343,12 @@ static int qemudDomainCoreDump(virDomainPtr dom, int flags ATTRIBUTE_UNUSED) { struct qemud_driver *driver = dom-conn-privateData; virDomainObjPtr vm; -char *command = NULL; -char *info = NULL; -char *safe_path = NULL; int resume = 0, paused = 0; int ret = -1; +const char *args[] = { +cat, +NULL, +}; qemuDriverLock(driver); vm = virDomainFindByUUID(driver-domains, dom-uuid); @@ -3427,43 +3380,9 @@ static int qemudDomainCoreDump(virDomainPtr dom, paused = 1; } -/* Migrate to file
[libvirt] [PATCH 20/27] Add API for issuing 'pci_add storage' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new API qemuMonitorAddPCIDisk() * src/qemu/qemu_driver.c: Convert over to using the new qemuMonitorAddPCIDisk() method, and remove now obsolete qemudEscape() method --- src/qemu/qemu_driver.c | 130 ++--- src/qemu/qemu_monitor_text.c | 55 ++ src/qemu/qemu_monitor_text.h | 13 3 files changed, 75 insertions(+), 123 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 10fc09a..b447a87 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3093,83 +3093,6 @@ cleanup: } -static char *qemudEscape(const char *in, int shell) -{ -int len = 0; -int i, j; -char *out; - -/* To pass through the QEMU monitor, we need to use escape - sequences: \r, \n, \, \\ - - To pass through both QEMU + the shell, we need to escape - the single character ' as the five characters '\\'' -*/ - -for (i = 0; in[i] != '\0'; i++) { -switch(in[i]) { -case '\r': -case '\n': -case '': -case '\\': -len += 2; -break; -case '\'': -if (shell) -len += 5; -else -len += 1; -break; -default: -len += 1; -break; -} -} - -if (VIR_ALLOC_N(out, len + 1) 0) -return NULL; - -for (i = j = 0; in[i] != '\0'; i++) { -switch(in[i]) { -case '\r': -out[j++] = '\\'; -out[j++] = 'r'; -break; -case '\n': -out[j++] = '\\'; -out[j++] = 'n'; -break; -case '': -case '\\': -out[j++] = '\\'; -out[j++] = in[i]; -break; -case '\'': -if (shell) { -out[j++] = '\''; -out[j++] = '\\'; -out[j++] = '\\'; -out[j++] = '\''; -out[j++] = '\''; -} else { -out[j++] = in[i]; -} -break; -default: -out[j++] = in[i]; -break; -} -} -out[j] = '\0'; - -return out; -} - -static char *qemudEscapeMonitorArg(const char *in) -{ -return qemudEscape(in, 0); -} - #define QEMUD_SAVE_MAGIC LibvirtQemudSave #define QEMUD_SAVE_VERSION 2 @@ -4626,12 +4549,8 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { -int ret, i; -char *cmd, *reply; -char *safe_path; +int i; const char* type = virDomainDiskBusTypeToString(dev-data.disk-bus); -int tryOldSyntax = 0; -unsigned domain, bus, slot; for (i = 0 ; i vm-def-ndisks ; i++) { if (STREQ(vm-def-disks[i]-dst, dev-data.disk-dst)) { @@ -4646,48 +4565,13 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, return -1; } -try_command: -safe_path = qemudEscapeMonitorArg(dev-data.disk-src); -if (!safe_path) { -virReportOOMError(conn); -return -1; -} - -ret = virAsprintf(cmd, pci_add %s storage file=%s,if=%s, - (tryOldSyntax ? 0: pci_addr=auto), safe_path, type); -VIR_FREE(safe_path); -if (ret == -1) { -virReportOOMError(conn); -return ret; -} - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(cannot attach %s disk), type); -VIR_FREE(cmd); +if (qemuMonitorAddPCIDisk(vm, + dev-data.disk-src, + type, + dev-data.disk-pci_addr.domain, + dev-data.disk-pci_addr.bus, + dev-data.disk-pci_addr.slot) 0) return -1; -} - -VIR_FREE(cmd); - -if (qemudParsePciAddReply(vm, reply, domain, bus, slot) 0) { -if (!tryOldSyntax strstr(reply, invalid char in expression)) { -VIR_FREE(reply); -tryOldSyntax = 1; -goto try_command; -} - -qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(adding %s disk failed: %s), type, reply); -VIR_FREE(reply); -return -1; -} - -VIR_FREE(reply); - -dev-data.disk-pci_addr.domain = domain; -dev-data.disk-pci_addr.bus= bus; -dev-data.disk-pci_addr.slot = slot; virDomainDiskInsertPreAlloced(vm-def, dev-data.disk); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 290dcce..765a482 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1437,6 +1437,61 @@ cleanup: } +int qemuMonitorAddPCIDisk(const virDomainObjPtr vm, +
[libvirt] [PATCH 18/27] Add API for issugin 'pci_add host' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new API qemuMonitorAddPCIHostDevice() * src/qemu/qemu_driver.c: Switch to using qemuMonitorAddPCIHostDevice() for PCI host device hotplug --- src/qemu/qemu_driver.c | 46 +++- src/qemu/qemu_monitor_text.c | 121 ++ src/qemu/qemu_monitor_text.h | 11 3 files changed, 140 insertions(+), 38 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f33c24e..e9e7543 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4903,8 +4903,6 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, virDomainDeviceDefPtr dev) { virDomainHostdevDefPtr hostdev = dev-data.hostdev; -char *cmd, *reply; -unsigned domain, bus, slot; pciDevice *pci; if (VIR_REALLOC_N(vm-def-hostdevs, vm-def-nhostdevs+1) 0) { @@ -4931,51 +4929,23 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, return -1; } -cmd = reply = NULL; - -if (virAsprintf(cmd, pci_add pci_addr=auto host host=%.2x:%.2x.%.1x, -hostdev-source.subsys.u.pci.bus, -hostdev-source.subsys.u.pci.slot, -hostdev-source.subsys.u.pci.function) 0) { -virReportOOMError(conn); -goto error; -} - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(cannot attach host pci device)); +if (qemuMonitorAddPCIHostDevice(vm, +hostdev-source.subsys.u.pci.domain, +hostdev-source.subsys.u.pci.bus, +hostdev-source.subsys.u.pci.slot, +hostdev-source.subsys.u.pci.function, + hostdev-source.subsys.u.pci.guest_addr.domain, + hostdev-source.subsys.u.pci.guest_addr.bus, + hostdev-source.subsys.u.pci.guest_addr.slot) 0) goto error; -} - -if (strstr(reply, invalid type: host)) { -qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, %s, - _(PCI device assignment is not supported by this version of qemu)); -goto error; -} - -if (qemudParsePciAddReply(vm, reply, domain, bus, slot) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(parsing pci_add reply failed: %s), reply); -goto error; -} - -hostdev-source.subsys.u.pci.guest_addr.domain = domain; -hostdev-source.subsys.u.pci.guest_addr.bus= bus; -hostdev-source.subsys.u.pci.guest_addr.slot = slot; vm-def-hostdevs[vm-def-nhostdevs++] = hostdev; -VIR_FREE(reply); -VIR_FREE(cmd); - return 0; error: pciDeviceListDel(conn, driver-activePciHostdevs, pci); -VIR_FREE(reply); -VIR_FREE(cmd); - return -1; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 0e0334c..ca84fc6 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1315,3 +1315,124 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm, VIR_FREE(addr); return ret; } + + +static int +qemuMonitorParsePciAddReply(virDomainObjPtr vm, +const char *reply, +unsigned *domain, +unsigned *bus, +unsigned *slot) +{ +char *s, *e; + +DEBUG(%s: pci_add reply: %s, vm-def-name, reply); + +/* If the command succeeds qemu prints: + * OK bus 0, slot XXX... + * or + * OK domain 0, bus 0, slot XXX + */ +if (!(s = strstr(reply, OK ))) +return -1; + +s += 3; + +if (STRPREFIX(s, domain )) { +s += strlen(domain ); + +if (virStrToLong_ui(s, e, 10, domain) == -1) { +VIR_WARN(_(Unable to parse domain number '%s'\n), s); +return -1; +} + +if (!STRPREFIX(e, , )) { +VIR_WARN(_(Expected ', ' parsing pci_add reply '%s'\n), s); +return -1; +} +s = e + 2; +} + +if (!STRPREFIX(s, bus )) { +VIR_WARN(_(Expected 'bus ' parsing pci_add reply '%s'\n), s); +return -1; +} +s += strlen(bus ); + +if (virStrToLong_ui(s, e, 10, bus) == -1) { +VIR_WARN(_(Unable to parse bus number '%s'\n), s); +return -1; +} + +if (!STRPREFIX(e, , )) { +VIR_WARN(_(Expected ', ' parsing pci_add reply '%s'\n), s); +return -1; +} +s = e + 2; + +if (!STRPREFIX(s, slot )) { +VIR_WARN(_(Expected 'slot ' parsing pci_add reply '%s'\n), s); +return -1; +} +s += strlen(slot ); + +if (virStrToLong_ui(s, e, 10, slot) == -1) { +
[libvirt] [PATCH 27/27] Fix crash in device hotplug cleanup code
* src/qemu/qemu_driver.c: Fix crash in scenario where XML parsing of hotplugged device failed thus 'dev' is NULL --- src/qemu/qemu_driver.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index da72913..7dc9353 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4880,7 +4880,7 @@ cleanup: if (cgroup) virCgroupFree(cgroup); -if (ret 0) { +if (ret 0 dev != NULL) { if (qemuDomainSetDeviceOwnership(dom-conn, driver, dev, 1) 0) VIR_WARN0(Fail to restore disk device ownership); virDomainDeviceDefFree(dev); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 03/27] Add API for 'change vnc password' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add a new qemuMonitorSetVNCPassword() API * src/qemu/qemu_driver.c: Refactor qemudInitPasswords to call qemuMonitorSetVNCPassword() --- src/qemu/qemu_driver.c | 24 src/qemu/qemu_monitor_text.c | 15 +++ src/qemu/qemu_monitor_text.h |3 +++ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 30d1468..e0b7c84 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1275,29 +1275,21 @@ qemudInitCpus(virConnectPtr conn, static int -qemudInitPasswords(virConnectPtr conn, - struct qemud_driver *driver, +qemudInitPasswords(struct qemud_driver *driver, virDomainObjPtr vm) { -char *info = NULL; +int ret = 0; if ((vm-def-ngraphics == 1) vm-def-graphics[0]-type == VIR_DOMAIN_GRAPHICS_TYPE_VNC (vm-def-graphics[0]-data.vnc.passwd || driver-vncPassword)) { -if (qemudMonitorCommandExtra(vm, change vnc password, - vm-def-graphics[0]-data.vnc.passwd ? - vm-def-graphics[0]-data.vnc.passwd : - driver-vncPassword, - QEMU_PASSWD_PROMPT, - -1, info) 0) { -qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - %s, _(setting VNC password failed)); -return -1; -} -VIR_FREE(info); +ret = qemuMonitorSetVNCPassword(vm, +vm-def-graphics[0]-data.vnc.passwd ? +vm-def-graphics[0]-data.vnc.passwd : +driver-vncPassword); } -return 0; +return ret; } @@ -2144,7 +2136,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, if ((qemudWaitForMonitor(conn, driver, vm, pos) 0) || (qemuDetectVcpuPIDs(conn, vm) 0) || (qemudInitCpus(conn, vm, migrateFrom) 0) || -(qemudInitPasswords(conn, driver, vm) 0) || +(qemudInitPasswords(driver, vm) 0) || (qemudDomainSetMemoryBalloon(conn, vm, vm-def-memory) 0) || (virDomainSaveStatus(conn, driver-stateDir, vm) 0)) { qemudShutdownVMDaemon(conn, driver, vm); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index d93e475..ba28f02 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -520,3 +520,18 @@ error: } +int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, + const char *password) +{ +char *info = NULL; +if (qemudMonitorCommandExtra(vm, change vnc password, + password, + QEMU_PASSWD_PROMPT, + -1, info) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + %s, _(setting VNC password failed)); +return -1; +} +VIR_FREE(info); +return 0; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 973c3b6..fd0fa61 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -71,4 +71,7 @@ int qemudMonitorSendCont(virConnectPtr conn, int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, int **pids); +int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, + const char *password); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 16/27] Add API for using 'usb_add' for disk devices
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorAddUSBDisk() API * src/qemu/qemu_driver.c: Switch USB disk hotplug to the new src/qemu/qemu_driver.c API. --- src/qemu/qemu_driver.c | 41 ++- src/qemu/qemu_monitor_text.c | 43 ++ src/qemu/qemu_monitor_text.h |4 +++ 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index da08af9..635fb84 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4698,59 +4698,32 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { -int ret, i; -char *safe_path; -char *cmd, *reply; +int i; for (i = 0 ; i vm-def-ndisks ; i++) { if (STREQ(vm-def-disks[i]-dst, dev-data.disk-dst)) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, +qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _(target %s already exists), dev-data.disk-dst); return -1; } } -if (VIR_REALLOC_N(vm-def-disks, vm-def-ndisks+1) 0) { -virReportOOMError(conn); -return -1; -} - -safe_path = qemudEscapeMonitorArg(dev-data.disk-src); -if (!safe_path) { -virReportOOMError(conn); +if (!dev-data.disk-src) { +qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + %s, _(disk source path is missing)); return -1; } -ret = virAsprintf(cmd, usb_add disk:%s, safe_path); -VIR_FREE(safe_path); -if (ret == -1) { +if (VIR_REALLOC_N(vm-def-disks, vm-def-ndisks+1) 0) { virReportOOMError(conn); -return ret; -} - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(cannot attach usb disk)); -VIR_FREE(cmd); return -1; } -DEBUG (%s: attach_usb reply: %s,vm-def-name, reply); -/* If the command failed qemu prints: - * Could not add ... */ -if (strstr(reply, Could not add )) { -qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, - _(adding usb disk failed)); -VIR_FREE(reply); -VIR_FREE(cmd); +if (qemuMonitorAddUSBDisk(vm, dev-data.disk-src) 0) return -1; -} virDomainDiskInsertPreAlloced(vm-def, dev-data.disk); -VIR_FREE(reply); -VIR_FREE(cmd); return 0; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index c154019..fd50cf2 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1199,3 +1199,46 @@ cleanup: VIR_FREE(dest); return ret; } + + +int qemuMonitorAddUSBDisk(const virDomainObjPtr vm, + const char *path) +{ +char *cmd = NULL; +char *safepath; +int ret = -1; +char *info = NULL; + +safepath = qemudEscapeMonitorArg(path); +if (!safepath) { +virReportOOMError(NULL); +return -1; +} + +if (virAsprintf(cmd, usb_add disk:%s, safepath) 0) { +virReportOOMError(NULL); +goto cleanup; +} + +if (qemudMonitorCommand(vm, cmd, info) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + %s, _(cannot run monitor command to add usb disk)); +goto cleanup; +} + +DEBUG (%s: usb_add reply: %s, vm-def-name, info); +/* If the command failed qemu prints: + * Could not add ... */ +if (strstr(info, Could not add )) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _(unable to add USB disk %s: %s), path, info); +goto cleanup; +} + +ret = 0; + +cleanup: +VIR_FREE(cmd); +VIR_FREE(safepath); +return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index ffed049..138e7a0 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -136,4 +136,8 @@ int qemuMonitorMigrateToCommand(const virDomainObjPtr vm, const char * const *argv, const char *target); + +int qemuMonitorAddUSBDisk(const virDomainObjPtr vm, + const char *path); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 00/27] Refactor QEMU monitor command handling
In the QEMU driver source code the methods which talk to the QEMU monitor currently all just call qemudMonitorCommand() directly with the raw command string, and then parse the raw reply. In the not too distant future QEMU is introducing a new machine parsable monitor syntax. With the current way the code is structured supporting this new mode will be seriously unpleasant. This large series of patches, moves all the monitor command formatting and parsing code out into a separate source file src/qemu/qemu_monitor_text.c. There is one API in that file for each logical monitor command we wish to issue, accepting (mostly) strongly typed arguments. The exception is the NIC hotplug method which still takes the raw NIC string for now. The main qemu_driver.c file now directly calls the appropriate monitor command APIs, making logic there much cleaner. When we add support for the new QEMU monitor syntax we'll gain another file src/qemu/qemu_monitor_json.c which implements all the same APIs as src/qemu/qemu_monitor_text.c, but using the new JSON syntax instead of raw text strings This patch series is soo large, because I did it in many small steps, one command at a time. It is also now much easier to debug the monitor by just setting the env variables LIBVIRT_LOG_OUTPUTS=1:stderr LIBVIRT_LOG_FILTERS=1:qemu_monitor And you'll get the command reply of each monitor interaction printed I've tested basic handling of every new method with the exception of the migration ones, since I don't have a convenient target host when on my laptop. Overall we get a small increase in code size, but huge increase in readability ! Makefile.am |1 libvirt_private.syms |1 qemu/qemu_conf.c | 20 qemu/qemu_conf.h |2 qemu/qemu_driver.c | 1669 +--- qemu/qemu_monitor_text.c | 1777 +++ qemu/qemu_monitor_text.h | 173 7 files changed, 2171 insertions(+), 1472 deletions(-) Daniel -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 11/27] Add API for issuing 'info blockstats' command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add a new qemuMonitorGetBlockStatsInfo() command * src/qemu/qemu_driver.c: Remove directly use of blockstats in favour of calling qemuMonitorGetBlockStatsInfo() --- src/qemu/qemu_driver.c | 95 +++-- src/qemu/qemu_monitor_text.c | 105 ++ src/qemu/qemu_monitor_text.h |8 +++ 3 files changed, 121 insertions(+), 87 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9c09024..f95c473 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5958,10 +5958,7 @@ qemudDomainBlockStats (virDomainPtr dom, struct _virDomainBlockStats *stats) { struct qemud_driver *driver = dom-conn-privateData; -char *dummy, *info = NULL; -const char *p, *eol; const char *qemu_dev_name = NULL; -size_t len; int i, ret = -1; virDomainObjPtr vm; virDomainDiskDefPtr disk = NULL; @@ -5998,95 +5995,19 @@ qemudDomainBlockStats (virDomainPtr dom, qemu_dev_name = qemudDiskDeviceName(dom-conn, disk); if (!qemu_dev_name) goto cleanup; -len = strlen (qemu_dev_name); -if (qemudMonitorCommand (vm, info blockstats, info) 0) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _('info blockstats' command failed)); -goto cleanup; -} -DEBUG (%s: info blockstats reply: %s, vm-def-name, info); - -/* If the command isn't supported then qemu prints the supported - * info commands, so the output starts info . Since this is - * unlikely to be the name of a block device, we can use this - * to detect if qemu supports the command. - */ -if (strstr(info, \ninfo )) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_NO_SUPPORT, - %s, - _('info blockstats' not supported by this qemu)); +if (qemuMonitorGetBlockStatsInfo(vm, qemu_dev_name, + stats-rd_req, + stats-rd_bytes, + stats-wr_req, + stats-wr_bytes, + stats-errs) 0) goto cleanup; -} - -stats-rd_req = -1; -stats-rd_bytes = -1; -stats-wr_req = -1; -stats-wr_bytes = -1; -stats-errs = -1; - -/* The output format for both qemu KVM is: - * blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=% - * (repeated for each block device) - * where '%' is a 64 bit number. - */ -p = info; - -while (*p) { -if (STREQLEN (p, qemu_dev_name, len) - p[len] == ':' p[len+1] == ' ') { - -eol = strchr (p, '\n'); -if (!eol) -eol = p + strlen (p); - -p += len+2; /* Skip to first label. */ - -while (*p) { -if (STRPREFIX (p, rd_bytes=)) { -p += 9; -if (virStrToLong_ll (p, dummy, 10, stats-rd_bytes) == -1) -DEBUG (%s: error reading rd_bytes: %s, - vm-def-name, p); -} else if (STRPREFIX (p, wr_bytes=)) { -p += 9; -if (virStrToLong_ll (p, dummy, 10, stats-wr_bytes) == -1) -DEBUG (%s: error reading wr_bytes: %s, - vm-def-name, p); -} else if (STRPREFIX (p, rd_operations=)) { -p += 14; -if (virStrToLong_ll (p, dummy, 10, stats-rd_req) == -1) -DEBUG (%s: error reading rd_req: %s, - vm-def-name, p); -} else if (STRPREFIX (p, wr_operations=)) { -p += 14; -if (virStrToLong_ll (p, dummy, 10, stats-wr_req) == -1) -DEBUG (%s: error reading wr_req: %s, - vm-def-name, p); -} else -DEBUG (%s: unknown block stat near %s, vm-def-name, p); - -/* Skip to next label. */ -p = strchr (p, ' '); -if (!p || p = eol) break; -p++; -} -ret = 0; -goto cleanup; -} -/* Skip to next line. */ -p = strchr (p, '\n'); -if (!p) break; -p++; -} +ret = 0; -/* If we reach here then the device was not found. */ -qemudReportError (dom-conn, dom, NULL, VIR_ERR_INVALID_ARG, - _(device not found: %s (%s)), path, qemu_dev_name); - cleanup: +cleanup: VIR_FREE(qemu_dev_name); -VIR_FREE(info); if (vm) virDomainObjUnlock(vm); return ret; diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index a5f43c5..f35b1ef 100644 ---
[libvirt] [PATCH 02/27] Add API for 'info cpus' monitor command
* src/qemu/qemu_monitor.h, src/qemu/qemu_monitor.c: Add a new qemuMonitorGetCPUInfo() command * src/qemu/qemu_driver.c: Refactor qemudDetectVcpuPIDs to use qemuMonitorGetCPUInfo() --- src/qemu/qemu_driver.c | 114 ++ src/qemu/qemu_monitor_text.c | 85 +++ src/qemu/qemu_monitor_text.h |4 +- 3 files changed, 115 insertions(+), 88 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9f17aae..30d1468 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -110,8 +110,8 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom); static int qemudDomainSetMemoryBalloon(virConnectPtr conn, virDomainObjPtr vm, unsigned long newmem); -static int qemudDetectVcpuPIDs(virConnectPtr conn, - virDomainObjPtr vm); +static int qemuDetectVcpuPIDs(virConnectPtr conn, + virDomainObjPtr vm); static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver, virDomainDefPtr def); @@ -1186,100 +1186,40 @@ qemudWaitForMonitor(virConnectPtr conn, } static int -qemudDetectVcpuPIDs(virConnectPtr conn, -virDomainObjPtr vm) { -char *qemucpus = NULL; -char *line; -int lastVcpu = -1; - -/* Only KVM has seperate threads for CPUs, - others just use main QEMU process for CPU */ -if (vm-def-virtType != VIR_DOMAIN_VIRT_KVM) -vm-nvcpupids = 1; -else -vm-nvcpupids = vm-def-vcpus; - -if (VIR_ALLOC_N(vm-vcpupids, vm-nvcpupids) 0) { -virReportOOMError(conn); -return -1; -} +qemuDetectVcpuPIDs(virConnectPtr conn, + virDomainObjPtr vm) { +pid_t *cpupids = NULL; +int ncpupids; if (vm-def-virtType != VIR_DOMAIN_VIRT_KVM) { +vm-nvcpupids = 1; +if (VIR_ALLOC_N(vm-vcpupids, vm-nvcpupids) 0) { +virReportOOMError(conn); +return -1; +} vm-vcpupids[0] = vm-pid; return 0; } -if (qemudMonitorCommand(vm, info cpus, qemucpus) 0) { -qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - %s, _(cannot run monitor command to fetch CPU thread info)); -VIR_FREE(vm-vcpupids); -vm-nvcpupids = 0; -return -1; -} - -/* - * This is the gross format we're about to parse :-{ - * - * (qemu) info cpus - * * CPU #0: pc=0x000f0c4a thread_id=30019 - * CPU #1: pc=0xfff0 thread_id=30020 - * CPU #2: pc=0xfff0 thread_id=30021 - * - */ -line = qemucpus; -do { -char *offset = strchr(line, '#'); -char *end = NULL; -int vcpu = 0, tid = 0; - -/* See if we're all done */ -if (offset == NULL) -break; +/* What follows is now all KVM specific */ -/* Extract VCPU number */ -if (virStrToLong_i(offset + 1, end, 10, vcpu) 0) -goto error; -if (end == NULL || *end != ':') -goto error; - -/* Extract host Thread ID */ -if ((offset = strstr(line, thread_id=)) == NULL) -goto error; -if (virStrToLong_i(offset + strlen(thread_id=), end, 10, tid) 0) -goto error; -if (end == NULL || !c_isspace(*end)) -goto error; - -/* Validate the VCPU is in expected range order */ -if (vcpu vm-nvcpupids || -vcpu != (lastVcpu + 1)) -goto error; - -lastVcpu = vcpu; -vm-vcpupids[vcpu] = tid; - -/* Skip to next data line */ -line = strchr(offset, '\r'); -if (line == NULL) -line = strchr(offset, '\n'); -} while (line != NULL); - -/* Validate we got data for all VCPUs we expected */ -if (lastVcpu != (vm-def-vcpus - 1)) -goto error; +if ((ncpupids = qemuMonitorGetCPUInfo(vm, cpupids)) 0) +return -1; -VIR_FREE(qemucpus); -return 0; +/* Treat failure to get VCPU-PID mapping as non-fatal */ +if (ncpupids == 0) +return 0; -error: -VIR_FREE(vm-vcpupids); -vm-nvcpupids = 0; -VIR_FREE(qemucpus); +if (ncpupids != vm-def-vcpus) { +qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _(got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d), + ncpupids, (int)vm-def-vcpus); +VIR_FREE(cpupids); +return -1; +} -/* Explicitly return success, not error. Older KVM does - not have vCPU - Thread mapping info and we don't - want to break its use. This merely disables ability - to pin vCPUS with libvirt */ +vm-nvcpupids = ncpupids; +vm-vcpupids = cpupids; return 0; } @@ -2202,7 +2142,7 @@ static int
[libvirt] [PATCH 12/27] Add API for issuing the 'migrate_set_speed' monitor command
* src/qemu/qemu_driver.c: Use new qemuMonitorSetMigrationSpeed() API during migration * src/qemu/qemu_monitor.h, src/qemu/qemu_monitor.c: Add new qemuMonitorSetMigrationSpeed() API --- src/qemu/qemu_driver.c | 11 +++ src/qemu/qemu_monitor_text.c | 28 src/qemu/qemu_monitor_text.h |3 +++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f95c473..ccc13c4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6530,14 +6530,9 @@ qemudDomainMigratePerform (virDomainPtr dom, event = NULL; } -if (resource 0) { -/* Issue migrate_set_speed command. Don't worry if it fails. */ -snprintf (cmd, sizeof cmd, migrate_set_speed %lum, resource); -qemudMonitorCommand (vm, cmd, info); - -DEBUG (%s: migrate_set_speed reply: %s, vm-def-name, info); -VIR_FREE (info); -} +if (resource 0 +qemuMonitorSetMigrationSpeed(vm, resource) 0) +goto cleanup; /* Issue the migrate command. */ safe_uri = qemudEscapeMonitorArg (uri); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index f35b1ef..d9227a2 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -969,3 +969,31 @@ int qemuMonitorSavePhysicalMemory(const virDomainObjPtr vm, { return qemuMonitorSaveMemory(vm, pmemsave, offset, length, path); } + + +int qemuMonitorSetMigrationSpeed(const virDomainObjPtr vm, + unsigned long bandwidth) +{ +char *cmd = NULL; +char *info = NULL; +int ret = -1; + +if (virAsprintf(cmd, migrate_set_speed %lum, bandwidth) 0) { +virReportOOMError(NULL); +goto cleanup; +} + +if (qemudMonitorCommand (vm, cmd, info) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(could restrict migration speed)); +goto cleanup; +} + +DEBUG (%s: migrate_set_speed reply: %s, vm-def-name, info); +ret = 0; + +cleanup: +VIR_FREE (info); +VIR_FREE(cmd); +return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index a047eba..0591f3c 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -109,4 +109,7 @@ int qemuMonitorSavePhysicalMemory(const virDomainObjPtr vm, size_t length, const char *path); +int qemuMonitorSetMigrationSpeed(const virDomainObjPtr vm, + unsigned long bandwidth); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 14/27] Add API for issuing a 'migrate' monitor command for TCP
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new API qemuMonitorMigrateToHost() for doing TCP migration * src/qemu/qemu_driver.c: Convert to use qemuMonitorMigrateToHost(). Also handle proper URIs (tcp:// as well as tcp:) --- src/qemu/qemu_driver.c | 40 - src/qemu/qemu_monitor_text.c | 56 ++ src/qemu/qemu_monitor_text.h |4 +++ 3 files changed, 77 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a6300c9..f234639 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6494,12 +6494,10 @@ qemudDomainMigratePerform (virDomainPtr dom, struct qemud_driver *driver = dom-conn-privateData; virDomainObjPtr vm; virDomainEventPtr event = NULL; -char *safe_uri; -char cmd[HOST_NAME_MAX+50]; -char *info = NULL; int ret = -1; int paused = 0; int status; +xmlURIPtr uribits = NULL; unsigned long long transferred, remaining, total; qemuDriverLock(driver); @@ -6537,34 +6535,29 @@ qemudDomainMigratePerform (virDomainPtr dom, goto cleanup; /* Issue the migrate command. */ -safe_uri = qemudEscapeMonitorArg (uri); -if (!safe_uri) { -virReportOOMError (dom-conn); -goto cleanup; +if (STRPREFIX(uri, tcp:) !STRPREFIX(uri, tcp://)) { +char *tmpuri; +if (virAsprintf(tmpuri, tcp://%s, uri + strlen(tcp:)) 0) { +virReportOOMError(dom-conn); +goto cleanup; +} +uribits = xmlParseURI(tmpuri); +VIR_FREE(tmpuri); +} else { +uribits = xmlParseURI(uri); } -snprintf (cmd, sizeof cmd, migrate \%s\, safe_uri); -VIR_FREE (safe_uri); - -if (qemudMonitorCommand (vm, cmd, info) 0) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(migrate operation failed)); +if (!uribits) { +qemudReportError(dom-conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _(cannot parse URI %s), uri); goto cleanup; } -DEBUG (%s: migrate reply: %s, vm-def-name, info); - -/* Now check for fail in the output string */ -if (strstr(info, fail) != NULL) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(migrate failed: %s), info); +if (qemuMonitorMigrateToHost(vm, uribits-server, uribits-port) 0) goto cleanup; -} /* it is also possible that the migrate didn't fail initially, but * rather failed later on. Check the output of info migrate */ -VIR_FREE(info); - if (qemuMonitorGetMigrationStatus(vm, status, transferred, remaining, @@ -6608,7 +6601,8 @@ cleanup: VIR_DOMAIN_EVENT_RESUMED_MIGRATED); } -VIR_FREE(info); +if (uribits) +xmlFreeURI(uribits); if (vm) virDomainObjUnlock(vm); if (event) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 0b746b9..4f8d72e 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1088,3 +1088,59 @@ cleanup: VIR_FREE(reply); return ret; } + + +static int qemuMonitorMigrate(const virDomainObjPtr vm, + const char *dest) +{ +char *cmd = NULL; +char *info = NULL; +int ret = -1; + +if (virAsprintf(cmd, migrate %s, cmd) 0) { +virReportOOMError(NULL); +return -1; +} + +if (qemudMonitorCommand(vm, cmd, info) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _(unable to start migration to %s), dest); +goto cleanup; +} + +DEBUG (%s: migrate reply: %s, vm-def-name, info); + +/* Now check for fail in the output string */ +if (strstr(info, fail) != NULL) { +qemudReportError (NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _(migration to '%s' failed: %s), dest, info); +goto cleanup; +} + + +ret = 0; + +cleanup: +VIR_FREE(info); +VIR_FREE(cmd); +return ret; +} + +int qemuMonitorMigrateToHost(const virDomainObjPtr vm, + const char *hostname, + int port) +{ +char *uri; +int ret; + +if (virAsprintf(uri, tcp:%s:%d, hostname, port) 0) { +virReportOOMError(NULL); +return -1; +} + +ret = qemuMonitorMigrate(vm, uri); + +VIR_FREE(uri); + +return ret; +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index c972672..0d34b6b 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -128,4 +128,8 @@ int qemuMonitorGetMigrationStatus(const virDomainObjPtr vm, unsigned long long *remaining,
[libvirt] [PATCH 26/27] Standardize debugging messages in QEMU monitor code
* src/qemu/qemu_monitor_text.c: Always print command and reply in qemuMonitorCommandWithHandler. Print all args in each monitor command API remove redundant relpy printing --- src/qemu/qemu_monitor_text.c | 82 ++--- 1 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 2c41288..abb2c0a 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -242,7 +242,7 @@ qemuMonitorCommandWithHandler(const virDomainObjPtr vm, qemuMonitorDiscardPendingData(vm); -VIR_DEBUG(Send '%s', cmd); +VIR_DEBUG(cmd='%s' extraPrompt='%s', cmd, NULLSTR(extraPrompt)); if (qemuMonitorSend(vm, cmd, scm_fd) 0) return -1; @@ -282,6 +282,7 @@ qemuMonitorCommandWithHandler(const virDomainObjPtr vm, (foundPrompt = strstr(buf, extraPrompt)) != NULL) { char *promptEnd; +DEBUG(prompt='%s' handler=%p, extraPrompt, extraHandler); if (extraHandler(vm, buf, foundPrompt, handlerData) 0) return -1; /* Discard output so far, necessary to detect whether @@ -320,6 +321,7 @@ qemuMonitorCommandWithHandler(const virDomainObjPtr vm, } } *reply = buf; +DEBUG(reply='%s', buf); return 0; error: @@ -521,11 +523,13 @@ qemuMonitorStartCPUs(virConnectPtr conn, const virDomainObjPtr vm) { char *reply; +DEBUG(vm=%p, pid=%d, id=%d, name=%s, vm, vm-pid, vm-def-id, vm-def-name); + if (qemuMonitorCommandWithHandler(vm, cont, ) is encrypted., qemuMonitorSendVolumePassphrase, conn, -1, reply) 0) return -1; -qemudDebug (%s: cont reply: %s, vm-def-name, info); + VIR_FREE(reply); return 0; } @@ -535,6 +539,8 @@ int qemuMonitorStopCPUs(const virDomainObjPtr vm) { char *info; +DEBUG(vm=%p, pid=%d, id=%d, name=%s, vm, vm-pid, vm-def-id, vm-def-name); + if (qemuMonitorCommand(vm, stop, info) 0) { qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, %s, _(cannot stop CPU execution)); @@ -548,6 +554,8 @@ qemuMonitorStopCPUs(const virDomainObjPtr vm) { int qemuMonitorSystemPowerdown(const virDomainObjPtr vm) { char *info; +DEBUG(vm=%p, pid=%d, id=%d, name=%s, vm, vm-pid, vm-def-id, vm-def-name); + if (qemuMonitorCommand(vm, system_powerdown, info) 0) { qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, %s, _(system shutdown operation failed)); @@ -567,6 +575,8 @@ int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, pid_t *cpupids = NULL; size_t ncpupids = 0; +DEBUG(vm=%p, pid=%d, id=%d, name=%s, vm, vm-pid, vm-def-id, vm-def-name); + if (qemuMonitorCommand(vm, info cpus, qemucpus) 0) { qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, %s, _(cannot run monitor command to fetch CPU thread info)); @@ -614,6 +624,7 @@ int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, if (VIR_REALLOC_N(cpupids, ncpupids+1) 0) goto error; +DEBUG(vcpu=%d pid=%d, vcpu, tid); cpupids[ncpupids++] = tid; lastVcpu = vcpu; @@ -655,13 +666,14 @@ int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm, int ret = -1; char *offset; +DEBUG(vm=%p, pid=%d, id=%d, name=%s, vm, vm-pid, vm-def-id, vm-def-name); + if (qemuMonitorCommand(vm, info balloon, reply) 0) { qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, %s, _(could not query memory balloon allocation)); return -1; } -DEBUG (%s: balloon reply: '%s', vm-def-name, reply); if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) { unsigned int memMB; char *end; @@ -700,12 +712,13 @@ int qemuMonitorGetBlockStatsInfo(const virDomainObjPtr vm, const char *p, *eol; int devnamelen = strlen(devname); +DEBUG(vm=%p, pid=%d, id=%d, name=%s dev=%s, vm, vm-pid, vm-def-id, vm-def-name, devname); + if (qemuMonitorCommand (vm, info blockstats, info) 0) { qemudReportError (NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, %s, _('info blockstats' command failed)); goto cleanup; } -DEBUG (%s: info blockstats reply: %s, vm-def-name, info); /* If the command isn't supported then qemu prints the supported * info commands, so the output starts info . Since this is @@ -795,6 +808,9 @@ int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, const char *password) { char *info = NULL; + +DEBUG(vm=%p, pid=%d, id=%d, name=%s, vm, vm-pid, vm-def-id, vm-def-name); + if (qemuMonitorCommandExtra(vm, change vnc password, password,
[libvirt] [PATCH 04/27] Rename qemudMonitorSendCont to qemuMonitorStartCPUs
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Rename Rename qemudMonitorSendCont to qemuMonitorStartCPUs * src/qemu/qemu_driver.c: Update callers for new name --- src/qemu/qemu_driver.c | 18 +- src/qemu/qemu_monitor_text.c |2 +- src/qemu/qemu_monitor_text.h |2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e0b7c84..1717cbd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1262,7 +1262,7 @@ qemudInitCpus(virConnectPtr conn, if (migrateFrom == NULL) { /* Allow the CPUS to start executing */ -if (qemudMonitorSendCont(conn, vm) 0) { +if (qemuMonitorStartCPUs(conn, vm) 0) { if (virGetLastError() == NULL) qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, %s, _(resume operation failed)); @@ -1275,8 +1275,8 @@ qemudInitCpus(virConnectPtr conn, static int -qemudInitPasswords(struct qemud_driver *driver, - virDomainObjPtr vm) { +qemuInitPasswords(struct qemud_driver *driver, + virDomainObjPtr vm) { int ret = 0; if ((vm-def-ngraphics == 1) @@ -2136,7 +2136,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, if ((qemudWaitForMonitor(conn, driver, vm, pos) 0) || (qemuDetectVcpuPIDs(conn, vm) 0) || (qemudInitCpus(conn, vm, migrateFrom) 0) || -(qemudInitPasswords(driver, vm) 0) || +(qemuInitPasswords(driver, vm) 0) || (qemudDomainSetMemoryBalloon(conn, vm, vm-def-memory) 0) || (virDomainSaveStatus(conn, driver-stateDir, vm) 0)) { qemudShutdownVMDaemon(conn, driver, vm); @@ -2819,7 +2819,7 @@ static int qemudDomainResume(virDomainPtr dom) { goto cleanup; } if (vm-state == VIR_DOMAIN_PAUSED) { -if (qemudMonitorSendCont(dom-conn, vm) 0) { +if (qemuMonitorStartCPUs(dom-conn, vm) 0) { if (virGetLastError() == NULL) qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, %s, _(resume operation failed)); @@ -3579,7 +3579,7 @@ cleanup: will support synchronous operations so we always get here after the migration is complete. */ if (resume paused) { -if (qemudMonitorSendCont(dom-conn, vm) 0) { +if (qemuMonitorStartCPUs(dom-conn, vm) 0) { if (virGetLastError() == NULL) qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, %s, _(resuming after dump failed)); @@ -4095,7 +4095,7 @@ static int qemudDomainRestore(virConnectPtr conn, /* If it was running before, resume it now. */ if (header.was_running) { -if (qemudMonitorSendCont(conn, vm) 0) { +if (qemuMonitorStartCPUs(conn, vm) 0) { if (virGetLastError() == NULL) qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, %s, _(failed to resume domain)); @@ -6828,7 +6828,7 @@ qemudDomainMigratePerform (virDomainPtr dom, cleanup: if (paused) { /* we got here through some sort of failure; start the domain again */ -if (qemudMonitorSendCont(dom-conn, vm) 0) { +if (qemuMonitorStartCPUs(dom-conn, vm) 0) { /* Hm, we already know we are in error here. We don't want to * overwrite the previous error, though, so we just throw something * to the logs and hope for the best @@ -6884,7 +6884,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, * = 0.10.6 to work properly. This isn't strictly necessary on * older qemu's, but it also doesn't hurt anything there */ -if (qemudMonitorSendCont(dconn, vm) 0) { +if (qemuMonitorStartCPUs(dconn, vm) 0) { if (virGetLastError() == NULL) qemudReportError(dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, %s, _(resume operation failed)); diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index ba28f02..3c12073 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -424,7 +424,7 @@ qemudMonitorSendVolumePassphrase(const virDomainObjPtr vm, } int -qemudMonitorSendCont(virConnectPtr conn, +qemuMonitorStartCPUs(virConnectPtr conn, const virDomainObjPtr vm) { char *reply; diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index fd0fa61..2632ecf 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -65,7 +65,7 @@ int qemudMonitorCommandExtra(const virDomainObjPtr vm, /* Formal APIs for each required monitor command */ -int qemudMonitorSendCont(virConnectPtr conn, +int qemuMonitorStartCPUs(virConnectPtr conn, const virDomainObjPtr vm); int
[libvirt] [PATCH 07/27] Add API for running 'info balloon' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Pull old qemudDomainGetMemoryBalloon() code into a new method called qemuMonitorGetBalloonInfo() * src/qemu/qemu_driver.c: Update to call qemuMonitorGetBalloonInfo() and remove qemudDomainGetMemoryBalloon(). --- src/qemu/qemu_driver.c | 62 ++--- src/qemu/qemu_monitor_text.c | 42 src/qemu/qemu_monitor_text.h |2 + 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 841ab68..8d3c9b6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2999,53 +2999,6 @@ cleanup: } -/* The reply from QEMU contains 'ballon: actual=421' where value is in MB */ -#define BALLOON_PREFIX balloon: actual= - -/* - * Returns: 0 if balloon not supported, +1 if balloon query worked - * or -1 on failure - */ -static int qemudDomainGetMemoryBalloon(virConnectPtr conn, - virDomainObjPtr vm, - unsigned long *currmem) { -char *reply = NULL; -int ret = -1; -char *offset; - -if (!virDomainIsActive(vm)) -return 0; - -if (qemudMonitorCommand(vm, info balloon, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(could not query memory balloon allocation)); -goto cleanup; -} - -DEBUG (%s: balloon reply: '%s', vm-def-name, reply); -if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) { -unsigned int memMB; -char *end; -offset += strlen(BALLOON_PREFIX); -if (virStrToLong_ui(offset, end, 10, memMB) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(could not parse memory balloon allocation)); -goto cleanup; -} -*currmem = memMB * 1024; -ret = 1; -} else { -/* We don't raise an error here, since its to be expected that - * many QEMU's don't support ballooning - */ -ret = 0; -} - -cleanup: -VIR_FREE(reply); -return ret; -} - /* * Returns: 0 if balloon not supported, +1 if balloon query worked * or -1 on failure @@ -3161,7 +3114,7 @@ static int qemudDomainGetInfo(virDomainPtr dom, info-maxMem = vm-def-maxmem; if (virDomainIsActive(vm)) { -err = qemudDomainGetMemoryBalloon(dom-conn, vm, balloon); +err = qemuMonitorGetBalloonInfo(vm, balloon); if (err 0) goto cleanup; @@ -4122,11 +4075,14 @@ static char *qemudDomainDumpXML(virDomainPtr dom, } /* Refresh current memory based on balloon info */ -err = qemudDomainGetMemoryBalloon(dom-conn, vm, balloon); -if (err 0) -goto cleanup; -if (err 0) -vm-def-memory = balloon; +if (virDomainIsActive(vm)) { +err = qemuMonitorGetBalloonInfo(vm, balloon); +if (err 0) +goto cleanup; +if (err 0) +vm-def-memory = balloon; +/* err == 0 indicates no balloon support, so ignore it */ +} ret = virDomainDefFormat(dom-conn, (flags VIR_DOMAIN_XML_INACTIVE) vm-newDef ? diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index ec5f670..2a20db3 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -547,6 +547,48 @@ error: } + +/* The reply from QEMU contains 'ballon: actual=421' where value is in MB */ +#define BALLOON_PREFIX balloon: actual= + +int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm, + unsigned long *currmem) +{ +char *reply = NULL; +int ret = -1; +char *offset; + +if (qemudMonitorCommand(vm, info balloon, reply) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(could not query memory balloon allocation)); +return -1; +} + +DEBUG (%s: balloon reply: '%s', vm-def-name, reply); +if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) { +unsigned int memMB; +char *end; +offset += strlen(BALLOON_PREFIX); +if (virStrToLong_ui(offset, end, 10, memMB) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _(could not parse memory balloon allocation from '%s'), reply); +goto cleanup; +} +*currmem = memMB * 1024; +ret = 1; +} else { +/* We don't raise an error here, since its to be expected that + * many QEMU's don't support ballooning + */ +ret = 0; +} + +cleanup: +VIR_FREE(reply); +return ret; +} + + int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, const char *password) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index
[libvirt] [PATCH 24/27] Add API for issuing 'host_net_remove' monitor command
* src/qemu/qemu_monitor.h, src/qemu/qemu_monitor.c: Add new qemuMonitorRemoveHostNetwork() command for removing host networks * src/qemu/qemu_driver.c: Convert NIC hotplug methods over to use qemuMonitorRemoveHostNetwork() --- src/qemu/qemu_driver.c | 65 ++--- src/qemu/qemu_monitor_text.c | 32 src/qemu/qemu_monitor_text.h |4 ++ 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index dfd5359..da72913 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4552,11 +4552,11 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, unsigned int qemuCmdFlags) { virDomainNetDefPtr net = dev-data.net; -char *cmd = NULL, *reply = NULL, *remove_cmd = NULL; char *tapfd_name = NULL; int i, tapfd = -1; char *nicstr = NULL; char *netstr = NULL; +int ret = -1; if (!(qemuCmdFlags QEMUD_CMD_FLAG_HOST_NET_ADD)) { qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, %s, @@ -4605,18 +4605,9 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, net-vlan, tapfd_name, netstr) 0) goto try_tapfd_close; -remove_cmd = NULL; -if (net-vlan = 0 net-hostnet_name -virAsprintf(remove_cmd, host_net_remove %d %s, -net-vlan, net-hostnet_name) 0) { -virReportOOMError(conn); -goto try_tapfd_close; -} - if (qemuMonitorAddHostNetwork(vm, netstr) 0) goto try_tapfd_close; -VIR_FREE(tapfd_name); if (tapfd != -1) close(tapfd); tapfd = -1; @@ -4630,28 +4621,28 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, net-pci_addr.slot) 0) goto try_remove; -VIR_FREE(netstr); -VIR_FREE(nicstr); -VIR_FREE(remove_cmd); +ret = 0; vm-def-nets[vm-def-nnets++] = net; -return 0; +cleanup: +VIR_FREE(nicstr); +VIR_FREE(netstr); +VIR_FREE(tapfd_name); +if (tapfd != -1) +close(tapfd); -try_remove: -VIR_FREE(reply); +return ret; -if (!remove_cmd) +try_remove: +if (!net-hostnet_name || net-vlan == 0) VIR_WARN0(_(Unable to remove network backend\n)); -else if (qemudMonitorCommand(vm, remove_cmd, reply) 0) -VIR_WARN(_(Failed to remove network backend with '%s'\n), remove_cmd); -else -VIR_DEBUG(%s: host_net_remove reply: %s\n, vm-def-name, reply); +else if (qemuMonitorRemoveHostNetwork(vm, net-vlan, net-hostnet_name) 0) +VIR_WARN(_(Failed to remove network backend for vlan %d, net %s), + net-vlan, net-hostnet_name); goto cleanup; try_tapfd_close: -VIR_FREE(reply); - if (tapfd_name qemuMonitorCloseFileHandle(vm, tapfd_name) 0) VIR_WARN(_(Failed to close tapfd with '%s'\n), tapfd_name); @@ -4660,16 +4651,7 @@ try_tapfd_close: no_memory: virReportOOMError(conn); -cleanup: -VIR_FREE(nicstr); -VIR_FREE(netstr); -VIR_FREE(cmd); -VIR_FREE(reply); -VIR_FREE(remove_cmd); -VIR_FREE(tapfd_name); -if (tapfd != -1) -close(tapfd); -return -1; +goto cleanup; } static int qemudDomainAttachHostPciDevice(virConnectPtr conn, @@ -4968,8 +4950,6 @@ qemudDomainDetachNetDevice(virConnectPtr conn, virDomainDeviceDefPtr dev) { int i, ret = -1; -char *cmd = NULL; -char *reply = NULL; virDomainNetDefPtr detach = NULL; for (i = 0 ; i vm-def-nnets ; i++) { @@ -5002,19 +4982,8 @@ qemudDomainDetachNetDevice(virConnectPtr conn, detach-pci_addr.slot) 0) goto cleanup; -if (virAsprintf(cmd, host_net_remove %d %s, -detach-vlan, detach-hostnet_name) 0) { -virReportOOMError(conn); +if (qemuMonitorRemoveHostNetwork(vm, detach-vlan, detach-hostnet_name) 0) goto cleanup; -} - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, - _(network device dettach command '%s' failed), cmd); -goto cleanup; -} - -DEBUG(%s: host_net_remove reply: %s, vm-def-name, reply); if (vm-def-nnets 1) { memmove(vm-def-nets + i, @@ -5034,8 +5003,6 @@ qemudDomainDetachNetDevice(virConnectPtr conn, ret = 0; cleanup: -VIR_FREE(reply); -VIR_FREE(cmd); return ret; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 5bff427..0675bf5 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1695,3 +1695,35 @@ cleanup: VIR_FREE(reply); return ret; } + + +int qemuMonitorRemoveHostNetwork(const virDomainObjPtr vm, + int vlan, + const char
[libvirt] [PATCH 09/27] Add APIs for issuing 'eject' and 'change dev' monitor commands
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new APis qemuMonitorChangeMedia and qemuMonitorEjectMedia. Pull in code for qemudEscape * src/qemu/qemu_driver.c: Remove code that directly issues 'eject' and 'change' commands in favour of API calls. --- src/qemu/qemu_driver.c | 52 +++--- src/qemu/qemu_monitor_text.c | 159 ++ src/qemu/qemu_monitor_text.h | 10 +++ 3 files changed, 178 insertions(+), 43 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a0b5e49..b15dc03 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4573,9 +4573,9 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn, unsigned int qemuCmdFlags) { virDomainDiskDefPtr origdisk = NULL, newdisk; -char *cmd, *reply, *safe_path; char *devname = NULL; int i; +int ret; origdisk = NULL; newdisk = dev-data.disk; @@ -4621,52 +4621,18 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn, } if (newdisk-src) { -safe_path = qemudEscapeMonitorArg(newdisk-src); -if (!safe_path) { -virReportOOMError(conn); -VIR_FREE(devname); -return -1; -} -if (virAsprintf(cmd, change %s \%s\, devname, safe_path) == -1) { -virReportOOMError(conn); -VIR_FREE(safe_path); -VIR_FREE(devname); -return -1; -} -VIR_FREE(safe_path); - -} else if (virAsprintf(cmd, eject %s, devname) == -1) { -virReportOOMError(conn); -VIR_FREE(devname); -return -1; -} -VIR_FREE(devname); - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(could not change cdrom media)); -VIR_FREE(cmd); -return -1; +ret = qemuMonitorChangeMedia(vm, devname, newdisk-src); +} else { +ret = qemuMonitorEjectMedia(vm, devname); } -/* If the command failed qemu prints: - * device not found, device is locked ... - * No message is printed on success it seems */ -DEBUG (%s: ejectable media change reply: %s, vm-def-name, reply); -if (strstr(reply, \ndevice )) { -qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(changing cdrom media failed: %s), reply); -VIR_FREE(reply); -VIR_FREE(cmd); -return -1; +if (ret == 0) { +VIR_FREE(origdisk-src); +origdisk-src = newdisk-src; +newdisk-src = NULL; +origdisk-type = newdisk-type; } -VIR_FREE(reply); -VIR_FREE(cmd); -VIR_FREE(origdisk-src); -origdisk-src = newdisk-src; -newdisk-src = NULL; -origdisk-type = newdisk-type; return 0; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index be13dce..8be8047 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -40,6 +40,84 @@ #define VIR_FROM_THIS VIR_FROM_QEMU +static char *qemudEscape(const char *in, int shell) +{ +int len = 0; +int i, j; +char *out; + +/* To pass through the QEMU monitor, we need to use escape + sequences: \r, \n, \, \\ + + To pass through both QEMU + the shell, we need to escape + the single character ' as the five characters '\\'' +*/ + +for (i = 0; in[i] != '\0'; i++) { +switch(in[i]) { +case '\r': +case '\n': +case '': +case '\\': +len += 2; +break; +case '\'': +if (shell) +len += 5; +else +len += 1; +break; +default: +len += 1; +break; +} +} + +if (VIR_ALLOC_N(out, len + 1) 0) +return NULL; + +for (i = j = 0; in[i] != '\0'; i++) { +switch(in[i]) { +case '\r': +out[j++] = '\\'; +out[j++] = 'r'; +break; +case '\n': +out[j++] = '\\'; +out[j++] = 'n'; +break; +case '': +case '\\': +out[j++] = '\\'; +out[j++] = in[i]; +break; +case '\'': +if (shell) { +out[j++] = '\''; +out[j++] = '\\'; +out[j++] = '\\'; +out[j++] = '\''; +out[j++] = '\''; +} else { +out[j++] = in[i]; +} +break; +default: +out[j++] = in[i]; +break; +} +} +out[j] = '\0'; + +return out; +} + +static char *qemudEscapeMonitorArg(const char *in) +{ +return qemudEscape(in, 0); +} + + /* Throw away any data available on the monitor * This is done before executing a command, in order * to allow
[libvirt] [PATCH 08/27] Add API for issuing 'balloon' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorSetBalloon() based on existing code in qemudDomainSetMemoryBalloon * src/qemu/qemu_driver.c: Remove use of qemudDomainSetMemoryBalloon() in favour of qemuMonitorSetBalloon(). Fix error code when balloon is not supported --- src/qemu/qemu_driver.c | 56 - src/qemu/qemu_monitor_text.c | 47 +++ src/qemu/qemu_monitor_text.h |2 + 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8d3c9b6..a0b5e49 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -107,9 +107,6 @@ static void qemudShutdownVMDaemon(virConnectPtr conn, static int qemudDomainGetMaxVcpus(virDomainPtr dom); -static int qemudDomainSetMemoryBalloon(virConnectPtr conn, - virDomainObjPtr vm, - unsigned long newmem); static int qemuDetectVcpuPIDs(virConnectPtr conn, virDomainObjPtr vm); @@ -2137,7 +2134,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, (qemuDetectVcpuPIDs(conn, vm) 0) || (qemudInitCpus(conn, vm, migrateFrom) 0) || (qemuInitPasswords(driver, vm) 0) || -(qemudDomainSetMemoryBalloon(conn, vm, vm-def-memory) 0) || +(qemuMonitorSetBalloon(vm, vm-def-memory) 0) || (virDomainSaveStatus(conn, driver-stateDir, vm) 0)) { qemudShutdownVMDaemon(conn, driver, vm); ret = -1; @@ -2999,50 +2996,6 @@ cleanup: } -/* - * Returns: 0 if balloon not supported, +1 if balloon query worked - * or -1 on failure - */ -static int qemudDomainSetMemoryBalloon(virConnectPtr conn, - virDomainObjPtr vm, - unsigned long newmem) { -char *cmd; -char *reply = NULL; -int ret = -1; - -/* - * 'newmem' is in KB, QEMU monitor works in MB, and we all wish - * we just worked in bytes with unsigned long long everywhere. - */ -if (virAsprintf(cmd, balloon %lu, (newmem / 1024)) 0) { -virReportOOMError(conn); -goto cleanup; -} - -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(could not balloon memory allocation)); -VIR_FREE(cmd); -goto cleanup; -} -VIR_FREE(cmd); - -/* If the command failed qemu prints: 'unknown command' - * No message is printed on success it seems */ -DEBUG (%s: balloon reply: %s,vm-def-name, reply); -if (strstr(reply, \nunknown command:)) { -/* Don't set error - it is expected memory balloon fails on many qemu */ -ret = 0; -} else { -ret = 1; -} - -cleanup: -VIR_FREE(reply); -return ret; -} - - static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { struct qemud_driver *driver = dom-conn-privateData; virDomainObjPtr vm; @@ -3066,10 +3019,13 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { } if (virDomainIsActive(vm)) { -ret = qemudDomainSetMemoryBalloon(dom-conn, vm, newmem); -if (ret == 0) +ret = qemuMonitorSetBalloon(vm, newmem); +/* Turn lack of balloon support into a fatal error */ +if (ret == 0) { qemudReportError(dom-conn, dom, NULL, VIR_ERR_NO_SUPPORT, %s, _(cannot set memory of an active domain)); +ret = -1; +} } else { vm-def-memory = newmem; ret = 0; diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 2a20db3..be13dce 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -551,6 +551,10 @@ error: /* The reply from QEMU contains 'ballon: actual=421' where value is in MB */ #define BALLOON_PREFIX balloon: actual= +/* + * Returns: 0 if balloon not supported, +1 if balloon query worked + * or -1 on failure + */ int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm, unsigned long *currmem) { @@ -604,3 +608,46 @@ int qemuMonitorSetVNCPassword(const virDomainObjPtr vm, VIR_FREE(info); return 0; } + +/* + * Returns: 0 if balloon not supported, +1 if balloon adjust worked + * or -1 on failure + */ +int qemuMonitorSetBalloon(const virDomainObjPtr vm, + unsigned long newmem) +{ +char *cmd; +char *reply = NULL; +int ret = -1; + +/* + * 'newmem' is in KB, QEMU monitor works in MB, and we all wish + * we just worked in bytes with unsigned long long everywhere. + */ +if (virAsprintf(cmd, balloon %lu, (newmem / 1024)) 0) { +virReportOOMError(NULL); +return -1; +} + +if (qemudMonitorCommand(vm, cmd, reply) 0) { +qemudReportError(NULL,
[libvirt] [PATCH 10/27] Add APIs for issuing 'memsave' and 'pmemsave' monitor commands
* src/qemu/qemu_monitor.h, src/qemu/qemu_monitor.c: Add new APIs qemuMonitorSaveVirtualMemory() and qemuMonitorSavePhysicalMemory() * src/qemu/qemu_driver.c: Use the new qemuMonitorSaveVirtualMemory() and qemuMonitorSavePhysicalMemory() APIs --- src/qemu/qemu_driver.c | 21 --- src/qemu/qemu_monitor_text.c | 54 ++ src/qemu/qemu_monitor_text.h | 10 +++ 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b15dc03..9c09024 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6233,7 +6233,6 @@ qemudDomainMemoryPeek (virDomainPtr dom, { struct qemud_driver *driver = dom-conn-privateData; virDomainObjPtr vm; -char cmd[256], *info = NULL; char *tmp = NULL; int fd = -1, ret = -1; @@ -6273,21 +6272,14 @@ qemudDomainMemoryPeek (virDomainPtr dom, goto cleanup; } -if (flags == VIR_MEMORY_VIRTUAL) -/* Issue the memsave command. */ -snprintf (cmd, sizeof cmd, memsave %llu %zi \%s\, offset, size, tmp); -else -/* Issue the pmemsave command. */ -snprintf (cmd, sizeof cmd, pmemsave %llu %zi \%s\, offset, size, tmp); - -if (qemudMonitorCommand (vm, cmd, info) 0) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _('memsave' command failed)); -goto cleanup; +if (flags == VIR_MEMORY_VIRTUAL) { +if (qemuMonitorSaveVirtualMemory(vm, offset, size, tmp) 0) +goto cleanup; +} else { +if (qemuMonitorSavePhysicalMemory(vm, offset, size, tmp) 0) +goto cleanup; } -DEBUG (%s: (p)memsave reply: %s, vm-def-name, info); - /* Read the memory file into buffer. */ if (saferead (fd, buffer, size) == (ssize_t) -1) { virReportSystemError (dom-conn, errno, @@ -6300,7 +6292,6 @@ qemudDomainMemoryPeek (virDomainPtr dom, cleanup: VIR_FREE(tmp); -VIR_FREE(info); if (fd = 0) close (fd); unlink (tmp); if (vm) diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 8be8047..a5f43c5 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -810,3 +810,57 @@ cleanup: return ret; } +static int qemuMonitorSaveMemory(const virDomainObjPtr vm, + const char *cmdtype, + unsigned long long offset, + size_t length, + const char *path) +{ +char *cmd = NULL; +char *reply = NULL; +char *safepath = NULL; +int ret = -1; + +if (!(safepath = qemudEscapeMonitorArg(path))) { +virReportOOMError(NULL); +goto cleanup; +} + +if (virAsprintf(cmd, %s %llu %zi \%s\, cmdtype, offset, length, safepath) 0) { +virReportOOMError(NULL); +goto cleanup; +} + +if (qemudMonitorCommand(vm, cmd, reply) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _(could save memory region to '%s'), path); +goto cleanup; +} + +/* XXX what is printed on failure ? */ + +ret = 0; + +cleanup: +VIR_FREE(cmd); +VIR_FREE(reply); +VIR_FREE(safepath); +return ret; +} + + +int qemuMonitorSaveVirtualMemory(const virDomainObjPtr vm, + unsigned long long offset, + size_t length, + const char *path) +{ +return qemuMonitorSaveMemory(vm, memsave, offset, length, path); +} + +int qemuMonitorSavePhysicalMemory(const virDomainObjPtr vm, + unsigned long long offset, + size_t length, + const char *path) +{ +return qemuMonitorSaveMemory(vm, pmemsave, offset, length, path); +} diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index d05dea1..dfe3445 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -91,4 +91,14 @@ int qemuMonitorChangeMedia(const virDomainObjPtr vm, const char *devname, const char *newmedia); + +int qemuMonitorSaveVirtualMemory(const virDomainObjPtr vm, + unsigned long long offset, + size_t length, + const char *path); +int qemuMonitorSavePhysicalMemory(const virDomainObjPtr vm, + unsigned long long offset, + size_t length, + const char *path); + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 23/27] Add API for issuing 'host_net_add' monitor command
* src/qemu/qemu_conf.h, src/qemu/qemu_conf.c: Remove prefix arg from qemuBuildHostNetStr which is no longer required * src/qemu/qemu_driver.c: Refactor to use qemuMonitorAddHostNetwork() API for adding host network * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorAddHostNetwork() method for adding host networks --- src/qemu/qemu_conf.c | 14 -- src/qemu/qemu_conf.h |1 - src/qemu/qemu_driver.c | 16 ++-- src/qemu/qemu_monitor_text.c | 30 ++ src/qemu/qemu_monitor_text.h |7 +++ 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index c531454..1d98637 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1287,7 +1287,6 @@ qemuBuildNicStr(virConnectPtr conn, int qemuBuildHostNetStr(virConnectPtr conn, virDomainNetDefPtr net, -const char *prefix, char type_sep, int vlan, const char *tapfd, @@ -1296,8 +1295,7 @@ qemuBuildHostNetStr(virConnectPtr conn, switch (net-type) { case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_BRIDGE: -if (virAsprintf(str, %stap%cfd=%s,vlan=%d%s%s, -prefix ? prefix : , +if (virAsprintf(str, tap%cfd=%s,vlan=%d%s%s, type_sep, tapfd, vlan, (net-hostnet_name ? ,name= : ), (net-hostnet_name ? net-hostnet_name : )) 0) { @@ -1310,8 +1308,6 @@ qemuBuildHostNetStr(virConnectPtr conn, { virBuffer buf = VIR_BUFFER_INITIALIZER; -if (prefix) -virBufferAdd(buf, prefix, strlen(prefix)); virBufferAddLit(buf, tap); if (net-ifname) { virBufferVSprintf(buf, %cifname=%s, type_sep, net-ifname); @@ -1355,8 +1351,7 @@ qemuBuildHostNetStr(virConnectPtr conn, break; } -if (virAsprintf(str, %ssocket%c%s=%s:%d,vlan=%d%s%s, -prefix ? prefix : , +if (virAsprintf(str, socket%c%s=%s:%d,vlan=%d%s%s, type_sep, mode, net-data.socket.address, net-data.socket.port, @@ -1371,8 +1366,7 @@ qemuBuildHostNetStr(virConnectPtr conn, case VIR_DOMAIN_NET_TYPE_USER: default: -if (virAsprintf(str, %suser%cvlan=%d%s%s, -prefix ? prefix : , +if (virAsprintf(str, user%cvlan=%d%s%s, type_sep, vlan, (net-hostnet_name ? ,name= : ), (net-hostnet_name ? net-hostnet_name : )) 0) { @@ -2014,7 +2008,7 @@ int qemudBuildCommandLine(virConnectPtr conn, goto no_memory; } -if (qemuBuildHostNetStr(conn, net, NULL, ',', +if (qemuBuildHostNetStr(conn, net, ',', net-vlan, tapfd_name, host) 0) { VIR_FREE(tapfd_name); goto error; diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 6ff5f0d..96b7c0c 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -170,7 +170,6 @@ int qemudBuildCommandLine (virConnectPtr conn, int qemuBuildHostNetStr (virConnectPtr conn, virDomainNetDefPtr net, - const char *prefix, char type_sep, int vlan, const char *tapfd, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6363edc..dfd5359 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4556,6 +4556,7 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, char *tapfd_name = NULL; int i, tapfd = -1; char *nicstr = NULL; +char *netstr = NULL; if (!(qemuCmdFlags QEMUD_CMD_FLAG_HOST_NET_ADD)) { qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, %s, @@ -4600,8 +4601,8 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, goto cleanup; } -if (qemuBuildHostNetStr(conn, net, host_net_add , ' ', -net-vlan, tapfd_name, cmd) 0) +if (qemuBuildHostNetStr(conn, net, ' ', +net-vlan, tapfd_name, netstr) 0) goto try_tapfd_close; remove_cmd = NULL; @@ -4612,16 +4613,9 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, goto try_tapfd_close; } -if (qemudMonitorCommand(vm, cmd, reply) 0) { -qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(failed to add network backend with '%s'), cmd); +if (qemuMonitorAddHostNetwork(vm, netstr)
[libvirt] [PATCH 06/27] Add API for the 'system_powerdown' monitor command
* src/qemu/qemu_driver.c: Remove use of 'system_powerdown' * src/qemu/qemu_monitor.h, src/qemu/qemu_monitor.c: Add a new qemuMonitorSystemPowerdown() api call --- src/qemu/qemu_driver.c |8 ++-- src/qemu/qemu_monitor_text.c | 14 ++ src/qemu/qemu_monitor_text.h |2 ++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5ebd4b7..841ab68 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2841,7 +2841,6 @@ cleanup: static int qemudDomainShutdown(virDomainPtr dom) { struct qemud_driver *driver = dom-conn-privateData; virDomainObjPtr vm; -char* info; int ret = -1; qemuDriverLock(driver); @@ -2862,12 +2861,9 @@ static int qemudDomainShutdown(virDomainPtr dom) { goto cleanup; } -if (qemudMonitorCommand(vm, system_powerdown, info) 0) { -qemudReportError(dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(shutdown operation failed)); +if (qemuMonitorSystemPowerdown(vm) 0) goto cleanup; -} -VIR_FREE(info); + ret = 0; cleanup: diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index ec30e72..ec5f670 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -451,6 +451,20 @@ qemuMonitorStopCPUs(const virDomainObjPtr vm) { return 0; } + +int qemuMonitorSystemPowerdown(const virDomainObjPtr vm) { +char *info; + +if (qemudMonitorCommand(vm, system_powerdown, info) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(system shutdown operation failed)); +return -1; +} +VIR_FREE(info); +return 0; +} + + int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, int **pids) { diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index eb1ba44..342a3f3 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -69,6 +69,8 @@ int qemuMonitorStartCPUs(virConnectPtr conn, const virDomainObjPtr vm); int qemuMonitorStopCPUs(const virDomainObjPtr vm); +int qemuMonitorSystemPowerdown(const virDomainObjPtr vm); + int qemuMonitorGetCPUInfo(const virDomainObjPtr vm, int **pids); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 13/27] Add API for running 'info migration' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorGetMigrationStatus() command. * src/qemu/qemu_driver.c: Use new qemuMonitorGetMigrationStatus() command to check completion status. --- src/qemu/qemu_driver.c | 15 +-- src/qemu/qemu_monitor_text.c | 91 ++ src/qemu/qemu_monitor_text.h | 16 +++ 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ccc13c4..a6300c9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6499,6 +6499,8 @@ qemudDomainMigratePerform (virDomainPtr dom, char *info = NULL; int ret = -1; int paused = 0; +int status; +unsigned long long transferred, remaining, total; qemuDriverLock(driver); vm = virDomainFindByUUID(driver-domains, dom-uuid); @@ -6562,14 +6564,17 @@ qemudDomainMigratePerform (virDomainPtr dom, * rather failed later on. Check the output of info migrate */ VIR_FREE(info); -if (qemudMonitorCommand(vm, info migrate, info) 0) { -qemudReportError (dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - %s, _(could not get info about migration)); + +if (qemuMonitorGetMigrationStatus(vm, status, + transferred, + remaining, + total) 0) { goto cleanup; } -if (strstr(info, fail) != NULL) { + +if (status != QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) { qemudReportError (dom-conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _(migrate failed: %s), info); + %s, _(migrate did not successfully complete)); goto cleanup; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index d9227a2..0b746b9 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -28,6 +28,7 @@ #include sys/un.h #include poll.h #include unistd.h +#include string.h #include qemu_monitor_text.h #include qemu_conf.h @@ -997,3 +998,93 @@ cleanup: VIR_FREE(cmd); return ret; } + + +#define MIGRATION_PREFIX Migration status: +#define MIGRATION_TRANSFER_PREFIX transferred ram: +#define MIGRATION_REMAINING_PREFIX remaining ram: +#define MIGRATION_TOTAL_PREFIX total ram: + +VIR_ENUM_DECL(qemuMonitorMigrationStatus) +VIR_ENUM_IMPL(qemuMonitorMigrationStatus, + QEMU_MONITOR_MIGRATION_STATUS_LAST, + inactive, active, completed, failed, cancelled) + +int qemuMonitorGetMigrationStatus(const virDomainObjPtr vm, + int *status, + unsigned long long *transferred, + unsigned long long *remaining, + unsigned long long *total) { +char *reply; +char *tmp; +char *end; +int ret = -1; + +*status = QEMU_MONITOR_MIGRATION_STATUS_INACTIVE; +*transferred = 0; +*remaining = 0; +*total = 0; + +if (qemudMonitorCommand(vm, info migration, reply) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + %s, _(cannot query migration status)); +return -1; +} + +if ((tmp = strstr(reply, MIGRATION_PREFIX)) != NULL) { +tmp += strlen(MIGRATION_PREFIX); +end = strchr(tmp, '\n'); +*end = '\0'; + +if ((*status = qemuMonitorMigrationStatusTypeFromString(tmp)) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _(unexpected migration status in %s), reply); +goto cleanup; +} + +if (*status == QEMU_MONITOR_MIGRATION_STATUS_ACTIVE) { +tmp = end + 1; + +if (!(tmp = strstr(tmp, MIGRATION_TRANSFER_PREFIX))) +goto done; +tmp += strlen(MIGRATION_TRANSFER_PREFIX); + +if (virStrToLong_ull(tmp, NULL, 10, transferred) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _(cannot parse migration data transferred statistic %s), tmp); +goto cleanup; +} +*transferred *= 1024; + +if (!(tmp = strstr(tmp, MIGRATION_REMAINING_PREFIX))) +goto done; +tmp += strlen(MIGRATION_REMAINING_PREFIX); + +if (virStrToLong_ull(tmp, NULL, 10, remaining) 0) { +qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _(cannot parse migration data remaining statistic %s), tmp); +goto cleanup; +} +*remaining *= 1024; + +if (!(tmp = strstr(tmp, MIGRATION_TOTAL_PREFIX))) +goto done; +tmp += strlen(MIGRATION_TOTAL_PREFIX); + +if (virStrToLong_ull(tmp, NULL, 10,
[libvirt] [PATCH 22/27] Add API for issuing 'pci_add nic' monitor command
* src/qemu/qemu_conf.c: Remove separator from qemuBuildNicStr() args, and remove hardcoded 'nic' prefix. Leave it upto callers instead * src/qemu/qemu_driver.c: Switch over to using the new qemuMonitorAddPCINetwork() method for NIC hotplug * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new qemuMonitorAddPCINetwork API for PCI network device hotplug --- src/qemu/qemu_conf.c |6 +-- src/qemu/qemu_conf.h |1 - src/qemu/qemu_driver.c | 93 -- src/qemu/qemu_monitor_text.c | 36 src/qemu/qemu_monitor_text.h |9 5 files changed, 55 insertions(+), 90 deletions(-) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 309f171..c531454 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1263,14 +1263,12 @@ int qemuBuildNicStr(virConnectPtr conn, virDomainNetDefPtr net, const char *prefix, -char type_sep, int vlan, char **str) { if (virAsprintf(str, - %snic%cmacaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s%s%s, +%smacaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s%s%s%s, prefix ? prefix : , -type_sep, net-mac[0], net-mac[1], net-mac[2], net-mac[3], net-mac[4], net-mac[5], @@ -1988,7 +1986,7 @@ int qemudBuildCommandLine(virConnectPtr conn, qemuAssignNetNames(def, net) 0) goto no_memory; -if (qemuBuildNicStr(conn, net, NULL, ',', net-vlan, nic) 0) +if (qemuBuildNicStr(conn, net, nic,, net-vlan, nic) 0) goto error; if ((qargv[qargc++] = strdup(-net)) == NULL) { diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 82eb89f..6ff5f0d 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -179,7 +179,6 @@ int qemuBuildHostNetStr (virConnectPtr conn, int qemuBuildNicStr (virConnectPtr conn, virDomainNetDefPtr net, const char *prefix, - char type_sep, int vlan, char **str); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f8710a6..6363edc 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4478,72 +4478,6 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn, return 0; } -static int -qemudParsePciAddReply(virDomainObjPtr vm, - const char *reply, - unsigned *domain, - unsigned *bus, - unsigned *slot) -{ -char *s, *e; - -DEBUG(%s: pci_add reply: %s, vm-def-name, reply); - -/* If the command succeeds qemu prints: - * OK bus 0, slot XXX... - * or - * OK domain 0, bus 0, slot XXX - */ -if (!(s = strstr(reply, OK ))) -return -1; - -s += 3; - -if (STRPREFIX(s, domain )) { -s += strlen(domain ); - -if (virStrToLong_ui(s, e, 10, domain) == -1) { -VIR_WARN(_(Unable to parse domain number '%s'\n), s); -return -1; -} - -if (!STRPREFIX(e, , )) { -VIR_WARN(_(Expected ', ' parsing pci_add reply '%s'\n), s); -return -1; -} -s = e + 2; -} - -if (!STRPREFIX(s, bus )) { -VIR_WARN(_(Expected 'bus ' parsing pci_add reply '%s'\n), s); -return -1; -} -s += strlen(bus ); - -if (virStrToLong_ui(s, e, 10, bus) == -1) { -VIR_WARN(_(Unable to parse bus number '%s'\n), s); -return -1; -} - -if (!STRPREFIX(e, , )) { -VIR_WARN(_(Expected ', ' parsing pci_add reply '%s'\n), s); -return -1; -} -s = e + 2; - -if (!STRPREFIX(s, slot )) { -VIR_WARN(_(Expected 'slot ' parsing pci_add reply '%s'\n), s); -return -1; -} -s += strlen(slot ); - -if (virStrToLong_ui(s, e, 10, slot) == -1) { -VIR_WARN(_(Unable to parse slot number '%s'\n), s); -return -1; -} - -return 0; -} static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, virDomainObjPtr vm, @@ -4621,7 +4555,7 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, char *cmd = NULL, *reply = NULL, *remove_cmd = NULL; char *tapfd_name = NULL; int i, tapfd = -1; -unsigned domain, bus, slot; +char *nicstr = NULL; if (!(qemuCmdFlags QEMUD_CMD_FLAG_HOST_NET_ADD)) { qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, %s, @@ -4693,30 +4627,18 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, close(tapfd); tapfd = -1; -if (qemuBuildNicStr(conn, net, -
[libvirt] [PATCH 01/27] Pull QEMU monitor interaction out to separate file
Pull out all the QEMU monitor interaction code to a separate file. This will make life easier when we need to drop in a new implementation for the forthcoming QMP machine friendly monitor support. Next step is to add formal APIs for each monitor command, and remove direct commands for sending/receiving generic data. * src/Makefile.am: Add qemu_monitor.c to build * src/qemu/qemu_driver.c: Remove code for monitor interaction * src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: New file for monitor interaction --- src/Makefile.am |1 + src/qemu/qemu_driver.c | 426 + src/qemu/qemu_monitor_text.c | 437 ++ src/qemu/qemu_monitor_text.h | 72 +++ 4 files changed, 511 insertions(+), 425 deletions(-) create mode 100644 src/qemu/qemu_monitor_text.c create mode 100644 src/qemu/qemu_monitor_text.h diff --git a/src/Makefile.am b/src/Makefile.am index 9cbec47..7520e96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -169,6 +169,7 @@ VBOX_DRIVER_EXTRA_DIST = vbox/vbox_tmpl.c vbox/README QEMU_DRIVER_SOURCES = \ qemu/qemu_conf.c qemu/qemu_conf.h \ + qemu/qemu_monitor_text.c qemu/qemu_monitortext.h\ qemu/qemu_driver.c qemu/qemu_driver.h UML_DRIVER_SOURCES = \ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 25d983e..9f17aae 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -55,6 +55,7 @@ #include datatypes.h #include qemu_driver.h #include qemu_conf.h +#include qemu_monitor_text.h #include c-ctype.h #include event.h #include buf.h @@ -74,9 +75,6 @@ #define VIR_FROM_THIS VIR_FROM_QEMU -#define QEMU_CMD_PROMPT \n(qemu) -#define QEMU_PASSWD_PROMPT Password: - static int qemudShutdown(void); static void qemuDriverLock(struct qemud_driver *driver) @@ -88,12 +86,6 @@ static void qemuDriverUnlock(struct qemud_driver *driver) virMutexUnlock(driver-lock); } -/* Return -1 for error, 0 for success */ -typedef int qemudMonitorExtraPromptHandler(const virDomainObjPtr vm, - const char *buf, - const char *prompt, - void *data); - static void qemuDomainEventFlush(int timer, void *opaque); static void qemuDomainEventQueue(struct qemud_driver *driver, virDomainEventPtr event); @@ -115,28 +107,6 @@ static void qemudShutdownVMDaemon(virConnectPtr conn, static int qemudDomainGetMaxVcpus(virDomainPtr dom); -static int qemudMonitorCommand(const virDomainObjPtr vm, - const char *cmd, - char **reply); -static int qemudMonitorCommandWithFd(const virDomainObjPtr vm, - const char *cmd, - int scm_fd, - char **reply); -static int qemudMonitorCommandWithHandler(const virDomainObjPtr vm, - const char *cmd, - const char *extraPrompt, - qemudMonitorExtraPromptHandler extraHandler, - void *handlerData, - int scm_fd, - char **reply); -static int qemudMonitorCommandExtra(const virDomainObjPtr vm, -const char *cmd, -const char *extra, -const char *extraPrompt, -int scm_fd, -char **reply); -static int qemudMonitorSendCont(virConnectPtr conn, -const virDomainObjPtr vm); static int qemudDomainSetMemoryBalloon(virConnectPtr conn, virDomainObjPtr vm, unsigned long newmem); @@ -2411,400 +2381,6 @@ cleanup: } -/* Throw away any data available on the monitor - * This is done before executing a command, in order - * to allow re-synchronization if something went badly - * wrong in the past. it also deals with problem of - * QEMU *sometimes* re-printing its initial greeting - * when we reconnect to the monitor after restarts. - */ -static void -qemuMonitorDiscardPendingData(virDomainObjPtr vm) { -char buf[1024]; -int ret = 0; - -/* Monitor is non-blocking, so just loop till we - * get -1 or 0. Don't bother with detecting - * errors, since we'll deal with that better later */ -do { -ret = read(vm-monitor, buf, sizeof (buf)-1); -} while (ret 0); -} - -static int -qemudMonitorSendUnix(const virDomainObjPtr vm, - const
[libvirt] [PATCH] Remove hand-crafted UUID parsers
* src/libvirt.c: Remove hand-crafted UUID parsers in favour of calling virParseUUID --- src/libvirt.c | 56 +--- 1 files changed, 5 insertions(+), 51 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 9fb0617..74d62a4 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -1839,26 +1839,11 @@ virDomainLookupByUUIDString(virConnectPtr conn, const char *uuidstr) virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } -/* XXX: sexpr_uuid() also supports '---' format. - * We needn't it here. Right? - */ -ret = sscanf(uuidstr, - %02x%02x%02x%02x- - %02x%02x- - %02x%02x- - %02x%02x- - %02x%02x%02x%02x%02x%02x, - raw + 0, raw + 1, raw + 2, raw + 3, - raw + 4, raw + 5, raw + 6, raw + 7, - raw + 8, raw + 9, raw + 10, raw + 11, - raw + 12, raw + 13, raw + 14, raw + 15); - -if (ret!=VIR_UUID_BUFLEN) { + +if (virUUIDParse(uuidstr, uuid) 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } -for (i = 0; i VIR_UUID_BUFLEN; i++) -uuid[i] = raw[i] 0xFF; return virDomainLookupByUUID(conn, uuid[0]); @@ -5038,26 +5023,10 @@ virNetworkLookupByUUIDString(virConnectPtr conn, const char *uuidstr) goto error; } -/* XXX: sexpr_uuid() also supports '---' format. - * We needn't it here. Right? - */ -ret = sscanf(uuidstr, - %02x%02x%02x%02x- - %02x%02x- - %02x%02x- - %02x%02x- - %02x%02x%02x%02x%02x%02x, - raw + 0, raw + 1, raw + 2, raw + 3, - raw + 4, raw + 5, raw + 6, raw + 7, - raw + 8, raw + 9, raw + 10, raw + 11, - raw + 12, raw + 13, raw + 14, raw + 15); - -if (ret!=VIR_UUID_BUFLEN) { +if (virUUIDParse(uuidstr, uuid) 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } -for (i = 0; i VIR_UUID_BUFLEN; i++) -uuid[i] = raw[i] 0xFF; return virNetworkLookupByUUID(conn, uuid[0]); @@ -8887,26 +8856,11 @@ virSecretLookupByUUIDString(virConnectPtr conn, const char *uuidstr) virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } -/* XXX: sexpr_uuid() also supports '---' format. - * We needn't it here. Right? - */ -ret = sscanf(uuidstr, - %02x%02x%02x%02x- - %02x%02x- - %02x%02x- - %02x%02x- - %02x%02x%02x%02x%02x%02x, - raw + 0, raw + 1, raw + 2, raw + 3, - raw + 4, raw + 5, raw + 6, raw + 7, - raw + 8, raw + 9, raw + 10, raw + 11, - raw + 12, raw + 13, raw + 14, raw + 15); - -if (ret!=VIR_UUID_BUFLEN) { + +if (virUUIDParse(uuidstr, uuid) 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } -for (i = 0; i VIR_UUID_BUFLEN; i++) -uuid[i] = raw[i] 0xFF; return virSecretLookupByUUID(conn, uuid[0]); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] node device devicekit backend
I've been looking at implementing a libudev backed node device, and I noticed that the devicekit node device backend doesn't build. Since I believe DeviceKit is deprecated for this sort of use, and AFAIK the DeviceKit support was never functionally equivalent to the HAL support, I'm wondering if we can just drop DeviceKit support. It also drags in glib, which is a separate problem. Opinions? Dave -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] 0.7.1 compile fails on opensuse 11.1
Pritesh Kothari wrote: it seems openSuSE 11.1 does not come with a pkgconfig for the device-mapper-devel package. I created a bug [1] for opensuse but was also told to mention it here so configure.in could be patched once the bug was fixed. Hi All, Just fixed this for ubuntu (should work now for suse as well) with some help from danpb and DV. The patch is attached below. ACK to this patch btw, it does solve the problem in SuSE distros where device-mapper-devel is missing pkgconfig file. But the problem is really a bug in the devel package, so will this workaround be committed to libvirt configure script? Thanks, Jim -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] PATCH] Stop double free
The stack trace is as follows: Program received signal SIGABRT, Aborted. 0x0035ad830265 in raise () from /lib64/libc.so.6 (gdb) bt #0 0x0035ad830265 in raise () from /lib64/libc.so.6 #1 0x0035ad831d10 in abort () from /lib64/libc.so.6 #2 0x0035ad86a84b in __libc_message () from /lib64/libc.so.6 #3 0x0035ad8722ef in _int_free () from /lib64/libc.so.6. #4 0x0035ad87273b in free () from /lib64/libc.so.6. #5 0x00406771 in vshDeinit (ctl=0x7fffd35d35e0) at virsh.c:8244 #6 0x004069a5 in vshError (ctl=0x7fffd35d35e0, doexit=value optimized out, format=0x414f66 %s) at virsh.c:7861 #7 0x004067c4 in vshDeinit (ctl=0x7fffd35d35e0) at virsh.c:8248 #8 0x0041335e in main (argc=3, argv=0x7fffd35d3748) at virsh.c:8493 I am trying to run libvirt-0.7.1-0.1.git3ef2e05.fc12.src.rpm on RHEL5.4. vshDeinit gets called twice, so ctl-name is freed twice. How about this patch then? (See attached file: 0001-Fix-possible-double-free.patch) -- Mark You must be the change you wish to see in the world. -- Mahatma Gandhi Worrying is praying for that you do not wish to happen. Chris Lalancette clala...@redhat. com To Mark Hamzy/Austin/i...@ibmus 09/16/2009 06:30 cc AMlibvir-list@redhat.com Subject Re: [libvirt] PATCH] Stop double free Mark Hamzy wrote: diff --git a/src/virsh.c b/src/virsh.c index 4825f1c..5fc6c8f 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -8201,7 +8201,7 @@ vshError(vshControl *ctl, int doexit, const char *format, ...) fputc('\n', stderr); if (doexit) { - if (ctl) + if (ctl ctl-conn) vshDeinit(ctl); exit(EXIT_FAILURE); } I don't think this patch is right. vshDeinit() already has a check for ctl-conn, and if you put it higher up in the call chain like this, you'll leak the ctl-name memory and the ctrl-log_fd file descriptors. Do you have a stack trace with line numbers in it (i.e. debugging information)? Also, what version of libvirt are you using? That might shed a bit more light on what the problem is. -- Chris Lalancette inline: graycol.gifinline: pic31299.gifinline: ecblank.gif 0001-Fix-possible-double-free.patch Description: Binary data -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Remove hand-crafted UUID parsers
2009/9/24 Daniel P. Berrange berra...@redhat.com: * src/libvirt.c: Remove hand-crafted UUID parsers in favour of calling virParseUUID s/virParseUUID/virUUIDParse/ --- src/libvirt.c | 56 +--- 1 files changed, 5 insertions(+), 51 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 9fb0617..74d62a4 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -1839,26 +1839,11 @@ virDomainLookupByUUIDString(virConnectPtr conn, const char *uuidstr) virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } - /* XXX: sexpr_uuid() also supports '---' format. - * We needn't it here. Right? - */ - ret = sscanf(uuidstr, - %02x%02x%02x%02x- - %02x%02x- - %02x%02x- - %02x%02x- - %02x%02x%02x%02x%02x%02x, - raw + 0, raw + 1, raw + 2, raw + 3, - raw + 4, raw + 5, raw + 6, raw + 7, - raw + 8, raw + 9, raw + 10, raw + 11, - raw + 12, raw + 13, raw + 14, raw + 15); - - if (ret!=VIR_UUID_BUFLEN) { + + if (virUUIDParse(uuidstr, uuid) 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } - for (i = 0; i VIR_UUID_BUFLEN; i++) - uuid[i] = raw[i] 0xFF; return virDomainLookupByUUID(conn, uuid[0]); @@ -5038,26 +5023,10 @@ virNetworkLookupByUUIDString(virConnectPtr conn, const char *uuidstr) goto error; } - /* XXX: sexpr_uuid() also supports '---' format. - * We needn't it here. Right? - */ - ret = sscanf(uuidstr, - %02x%02x%02x%02x- - %02x%02x- - %02x%02x- - %02x%02x- - %02x%02x%02x%02x%02x%02x, - raw + 0, raw + 1, raw + 2, raw + 3, - raw + 4, raw + 5, raw + 6, raw + 7, - raw + 8, raw + 9, raw + 10, raw + 11, - raw + 12, raw + 13, raw + 14, raw + 15); - - if (ret!=VIR_UUID_BUFLEN) { + if (virUUIDParse(uuidstr, uuid) 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } - for (i = 0; i VIR_UUID_BUFLEN; i++) - uuid[i] = raw[i] 0xFF; return virNetworkLookupByUUID(conn, uuid[0]); @@ -8887,26 +8856,11 @@ virSecretLookupByUUIDString(virConnectPtr conn, const char *uuidstr) virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } - /* XXX: sexpr_uuid() also supports '---' format. - * We needn't it here. Right? - */ - ret = sscanf(uuidstr, - %02x%02x%02x%02x- - %02x%02x- - %02x%02x- - %02x%02x- - %02x%02x%02x%02x%02x%02x, - raw + 0, raw + 1, raw + 2, raw + 3, - raw + 4, raw + 5, raw + 6, raw + 7, - raw + 8, raw + 9, raw + 10, raw + 11, - raw + 12, raw + 13, raw + 14, raw + 15); - - if (ret!=VIR_UUID_BUFLEN) { + + if (virUUIDParse(uuidstr, uuid) 0) { virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } - for (i = 0; i VIR_UUID_BUFLEN; i++) - uuid[i] = raw[i] 0xFF; return virSecretLookupByUUID(conn, uuid[0]); -- 1.6.2.5 You removed the usage of raw, i and ret in this 3 functions, but forgot to remove the variable definitions as well. ACK, beside the two comments. Matthias -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/9] Extend disk element with controller information
2009/9/24 Daniel P. Berrange berra...@redhat.com: Outside the scope of your patches, I think it would be worth adding a 'name' attribute to all devices in the libvirt XML as a standardized unique identifier. We already have to keep track of a 'name' internally for NIC hotplug with QEMU, and with QEMU's qdev work we're going to end up having to track a 'name' for pretty much all devices. Thus we might as well expose it in the XML Would this device name be read-only, or would it be editable/writable by the user (e.g. through virsh edit)? If it should be read-only, I see no problem supporting device names in the ESX driver. But If it should be editable/writable it may be a problem to implement this for the ESX driver, as I'm currently not aware of any sensible way to store such an custom device name in a persistent manner on an ESX server. Matthias -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Some problem with the save function
On 09/18/2009 03:09 AM, Charles Duffy wrote: Daniel P. Berrange wrote: Hmm, bad error message :-( We might also need todo a chown() in the restore path to allow QEMU to read it. NB there is no compatability between QEMU version, so if you have upgraded your install of QEMU between the time you saved restored it is very likely to crash burn. How difficult would it be to set up named pipes for save and restore operations, and splice from those pipes to the actual files on the libvirtd side? Seems much preferable from a security perspective to chown'ing things around, and (unlike pipes set up ahead of time with pipe() and friends) shouldn't be disrupted by a libvirtd restart. For a recent enough QEMU, you could also use the migrate-to-file-descriptor functionality which uses SCM_RIGHTS. It is in QEMU 0.12 only, but since the plumbing is in 0.11 too we could ask for a backport. Paolo -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list