Re: [libvirt] [PATCH v3 2/2] network: Add code for setting network bandwidth for ethernet interfaces
On 10/8/14, 8:39 PM, "Eric Blake" wrote: >On 10/08/2014 04:10 PM, Anirban Chakraborty wrote: > >>> Needs rework after my comments on 1/2. I also wonder if this should >>> just be folded in to that patch, and/or made into a switch statement >>> where the compiler forces us to think about any future >>> VIR_DOMAIN_NET_TYPE_* additions on whether they should return true or >>> false. > >>> bool virNetDevSupportBandwidth(virDomainNetType type) >>> { >>>switch (type) { >>>case VIR_DOMAIN_NET_TYPE_BRIDGE: >>>case VIR_DOMAIN_NET_TYPE_NETWORK: >>>case VIR_DOMAIN_NET_TYPE_DIRECT: >>>case VIR_DOMAIN_NET_TYPE_ETHERNET: >>>return true; >>>case VIR_DOMAIN_NET_TYPE_USER: >>>case VIR_DOMAIN_NET_TYPE_VHOSTUSER: >>>case VIR_DOMAIN_NET_TYPE_SERVER: >>>case VIR_DOMAIN_NET_TYPE_CLIENT: >>>case VIR_DOMAIN_NET_TYPE_MCAST: >>>case VIR_DOMAIN_NET_TYPE_INTERNAL: >>>case VIR_DOMAIN_NET_TYPE_HOSTDEV: >>>case VIR_DOMAIN_NET_TYPE_LAST: >>>/* cover all enums to appease the compiler */ ; >>>} >>>return false; >>> } >> >> We could have the function defined with a switch, however, instead of >> listing all the types, I could return false from the default case. >> >> Something like: >> switch (type) { >> case VIR_DOMAIN_NET_TYPE_BRIDGE: >> case VIR_DOMAIN_NET_TYPE_NETWORK: >> case VIR_DOMAIN_NET_TYPE_DIRECT: >> case VIR_DOMAIN_NET_TYPE_ETHERNET: >> return true; >> >> default; >> return false; > >Alas, using a default case means the compiler can no longer tell you >about missed cases. I wrote my example to intentionally spell out ALL >cases without a default, in order to ensure the compiler will loudly >warn if we add another enum in the future. I understood the intention. However, I was aiming for a compact code. If we add additional enums for network type, we should be adding those types in the above switch provided the new interface type supports bandwidth. I do not know if we should prevent future coding error by elaborating the current code. Forgive me, as I do not know the coding convention for libvirt. If this is the standard practice, I¹ll change the above switch as per your wish. Anirban -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [Question] capabilities.pidfile is left behind while starting and stopping libvirtd repeatly
On Wed, Oct 08, 2014 at 04:07:33PM +0800, Wang Rui wrote: On 2014/10/2 17:55, Martin Kletzander wrote: On Tue, Sep 30, 2014 at 10:26:21PM +0200, Guido Günther wrote: On Tue, Sep 30, 2014 at 04:47:14PM +0200, Martin Kletzander wrote: On Tue, Sep 30, 2014 at 05:34:54PM +0800, Wang Yufei wrote: >Hi, all > >I started and stopped libvirtd service repeatly with high frequency(1 per second), and found that the file capabilities.pidfile is left behind, as well as a qemu process. If I then restart libvirtd, qemu-kvm will fail to start as it's unable to flock capabilities.pidfile's fd. > Have you tried current master? Or at least -rc2? It should already be fixed there: commit 9e159b521dbf18c6da6976e54e29c8553f831eb6 Author: Guido Günther Date: Thu Sep 25 10:30:58 2014 +0200 qemu: remove capabilities.monitor.sock when done This one removes the monitor socket, not the pidfile since I didn't see that one lingering around in my tests. Cheers, Oh, sorry for that, my fault. Well, should the daemon just kill the process when it's dying in order to release the lock? If you try slower, we will properly remove the pidfile, won't we? Yes, the pidfile will be keep open and locked forever if this qemu process is alive. And it will be unlink if I shutdown libvitd daemon slower. But in this condition(started and stopped libvirtd service repeatly with high frequency) the pidfile is left behind. In fact libvirtd daemon is killed before qemu-kvm process and pidfile are cleaned up. Is it a problem? Simple kill(getpid(), SIGTERM) was enough to find out this is exactly what's happening. I have a fix prepared for this, but when I tried checking whether it fixes everything, I realized I can't find any problem this causes. And that's strange. All domain capabilities were in place even though I cleared them from the cache. Is there any cause of this problem? Does something not work then? I just want to know to test it basically :) Thanks for finding that out, Martin signature.asc Description: Digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 1/3] docs, conf, schema: add support for shmem device
On Wed, Oct 08, 2014 at 06:57:45PM +0200, Maxime Leroy wrote: Hi Martin, On Fri, Oct 3, 2014 at 10:45 PM, Martin Kletzander wrote: On Thu, Oct 02, 2014 at 09:42:36AM +0200, Michal Privoznik wrote: On 26.09.2014 12:43, Martin Kletzander wrote: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b114737..51bdd31 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c [..] Nice catch. Since we are past the release anyway, I'm going to push this in a while and whoever wants (e.g. Maxime) have the whole release cycle to test this. Thanks for pushing/cleaning the shmem patches support (i.e http://www.redhat.com/archives/libvir-list/2014-August/msg01032.html) But you did miss the following: 1. the ivshmem server autostart feature: you wanted me to develop it into the v1. (i.e. http://www.redhat.com/archives/libvir-list/2014-August/msg01432.html) Yes, I know. That was the idea that when the patches are split logically, it's possible to push one part without waiting for other one. 2. You did not wait for my tests. Why should I ask you to wait for my tests? Lucky enough, now I have the results of the tests, everything works fine ;) I don't understand why it became so urgent to push these patches. I'm sorry if I disappointed you somehow. At first I wanted to make it for the 1.2.9 release, so we might get some upstream and usage from libvirt users. Even though I didn't make it, I already had many reviews and it was easy to fix what people requested. And because I had some ACKs and it was after release, there's a whole release cycle to try out for everyone else if they want (unfortunately they can't try that with the official release, but have to go with git). If you doubt that, it already worked. Thanks to pushing it, Eric found some typos, Peter found out that there's no ABI stability check in qemu driver and that's just a start. Anyway, I am glad that libvirt supports ivshmem. Since now you pushed these patches, do you plan to provide the ivshmem autostart feature like you requested previously ? I'll be glad to review it and to provide feedbacks based on my tests. I did not plan to, so feel free to continue with that, I'm focusing on different things now. But if it's updated in qemu and there's no progress, I might look into that because it would be nice to have libvirt supporting the server as well. Have a nice day, Martin signature.asc Description: Digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/2] network: Add code for setting network bandwidth for ethernet interfaces
On 10/08/2014 04:10 PM, Anirban Chakraborty wrote: >> Needs rework after my comments on 1/2. I also wonder if this should >> just be folded in to that patch, and/or made into a switch statement >> where the compiler forces us to think about any future >> VIR_DOMAIN_NET_TYPE_* additions on whether they should return true or >> false. >> bool virNetDevSupportBandwidth(virDomainNetType type) >> { >>switch (type) { >>case VIR_DOMAIN_NET_TYPE_BRIDGE: >>case VIR_DOMAIN_NET_TYPE_NETWORK: >>case VIR_DOMAIN_NET_TYPE_DIRECT: >>case VIR_DOMAIN_NET_TYPE_ETHERNET: >>return true; >>case VIR_DOMAIN_NET_TYPE_USER: >>case VIR_DOMAIN_NET_TYPE_VHOSTUSER: >>case VIR_DOMAIN_NET_TYPE_SERVER: >>case VIR_DOMAIN_NET_TYPE_CLIENT: >>case VIR_DOMAIN_NET_TYPE_MCAST: >>case VIR_DOMAIN_NET_TYPE_INTERNAL: >>case VIR_DOMAIN_NET_TYPE_HOSTDEV: >>case VIR_DOMAIN_NET_TYPE_LAST: >>/* cover all enums to appease the compiler */ ; >>} >>return false; >> } > > We could have the function defined with a switch, however, instead of > listing all the types, I could return false from the default case. > > Something like: > switch (type) { > case VIR_DOMAIN_NET_TYPE_BRIDGE: > case VIR_DOMAIN_NET_TYPE_NETWORK: > case VIR_DOMAIN_NET_TYPE_DIRECT: > case VIR_DOMAIN_NET_TYPE_ETHERNET: > return true; > > default; > return false; Alas, using a default case means the compiler can no longer tell you about missed cases. I wrote my example to intentionally spell out ALL cases without a default, in order to ensure the compiler will loudly warn if we add another enum in the future. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 03/21] Added basic implementation for virConnectGetCapabilities (required Win32_ComputerSystemProduct class)
On 10/08/2014 06:33 AM, Yves Vinter wrote: > From: yvinter > Long subject line. I'd suggest: hyperv: add implementation for virConnectGetCapabilities Done by adding the Win32_ComputerSystemProduct class. > --- > src/hyperv/hyperv_driver.c| 112 > ++ > src/hyperv/hyperv_private.h | 2 + > src/hyperv/hyperv_wmi_generator.input | 12 > 3 files changed, 126 insertions(+) > > diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c > index f2017c3..dd56fb0 100644 > --- a/src/hyperv/hyperv_driver.c > +++ b/src/hyperv/hyperv_driver.c > @@ -58,12 +58,19 @@ hypervFreePrivate(hypervPrivate **priv) > wsmc_release((*priv)->client); > } > > +if ((*priv)->caps != NULL) > +virObjectUnref((*priv)->caps); Dead 'if'; virObjectUnref(NULL) is safe. > > +/* Forward declaration of hypervCapsInit */ > +static virCapsPtr hypervCapsInit(hypervPrivate *priv); Why do you need a forward declaration of a static function? If it's not recursive, just put the whole function body here (that may mean moving more than one function, to keep things topologically sorted; if you need to do code motion of existing functions, do it in a separate patch from where you add new code, to ease review). > > +/* Retrieves host system UUID */ > +static int > +hypervLookupHostSystemBiosUuid(hypervPrivate *priv, unsigned char *uuid) > +{ > +Win32_ComputerSystemProduct *computerSystem = NULL; > +virBuffer query = VIR_BUFFER_INITIALIZER; > +int result = -1; > + > +virBufferAddLit(&query, WIN32_COMPUTERSYSTEMPRODUCT_WQL_SELECT); > + > +if (hypervGetWin32ComputerSystemProductList(priv, &query, > &computerSystem) < 0) { > +goto cleanup; > +} > + > +if (computerSystem == NULL) { > +virReportError(VIR_ERR_NO_DOMAIN, Is VIR_ERR_NO_DOMAIN really the right error to be using here? > + _("Unable to get Win32_ComputerSystemProduct")); > +goto cleanup; > +} > + > +if (virUUIDParse(computerSystem->data->UUID, uuid) < 0) { > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not parse UUID from string '%s'"), > + computerSystem->data->UUID); > +goto cleanup; > +} > + > +result = 0; > + > + cleanup: > +hypervFreeObject(priv, (hypervObject *)computerSystem); > +virBufferFreeAndReset(&query); This virBufferFreeAndReset is not needed if you take my alternate patch for 1/21. > + > +return result; > +} > + > + > + > +static virCapsPtr hypervCapsInit(hypervPrivate *priv) Libvirt style is two blank lines between functions, and function name starting in column 1 of a line separate from the return type: static virCapsPtr hypervCapsInit(hypervPrivate *priv) > +{ > +virCapsPtr caps = NULL; > +virCapsGuestPtr guest = NULL; > + > +caps = virCapabilitiesNew(VIR_ARCH_X86_64, 1, 1); > + > +if (caps == NULL) { > +virReportOOMError(); > +return NULL; > +} > + > +/* virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 > }); */ Might be nice to explain why this is commented out. > +} > + > + > + > +static char* Only need two blank lines. > +hypervConnectGetCapabilities(virConnectPtr conn) > +{ > +hypervPrivate *priv = conn->privateData; > +char *xml = virCapabilitiesFormatXML(priv->caps); virCapabilitiesFormatXML can only return NULL on error, and it already outputs a decent error message; also, error is not always due to OOM... > + > +if (xml == NULL) { > +virReportOOMError(); ...so this virReportOOMError() is bogus, because it overwrites the decent message. > +return NULL; > +} Once you realize that, you can simplify this function to: static char* hypervConnectGetCapabilities(virConnectPtr conn) { hypervPrivate *priv = conn->privateData; return virCapabilitiesFormatXML(priv->caps); } -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 02/21] Added implementation for virConnectGetVersion (required CIM_DataFile class)
On 10/08/2014 06:33 AM, Yves Vinter wrote: > From: yvinter > > --- > src/hyperv/hyperv_driver.c| 55 > +++ > src/hyperv/hyperv_wmi_generator.input | 37 +++ > src/hyperv/hyperv_wmi_generator.py| 4 +-- > 3 files changed, 94 insertions(+), 2 deletions(-) > Another round of reviews; the .input and .py file look okay to me, but I spotted more issues in the .c that I didn't point out the first time around. > +static int > +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) > +{ > +int result = -1; > +hypervPrivate *priv = conn->privateData; > +CIM_DataFile *datafile = NULL; > +virBuffer query = VIR_BUFFER_INITIALIZER; > +char *p; > + Trailing whitespace. Another thing 'make syntax-check' will flag. > +virBufferAddLit(&query, " Select * from CIM_DataFile where > Name='c:windowssystem32vmms.exe' "); > +if (hypervGetCIMDataFileList(priv, &query, &datafile) < 0) { > +goto cleanup; > +} > + > +/* Check the result of convertion */ s/convertion/conversion/ > +if (datafile == NULL) { > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for domain %s"), > + "Msvm_VirtualSystemSettingData", > + datafile->data->Version); Is this error message correct? That is, is datafile->data->Version the name of the domain you are referring to in the message? > +goto cleanup; > +} > + > +/* Delete release number and last digit of build number 1.1.111x. */ > +p = strrchr(datafile->data->Version,'.'); > +if (p == NULL) { > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not parse version number from '%s'"), > + datafile->data->Version); > +goto cleanup; > +} > +p--; > +*p = '\0'; This is modifying datafile->data in-place. I hope that's safe (if not, you'd have to strdup a copy that you can safely manipulate locally). > + > +/* Parse Version String to Long */ > +if (virParseVersionString(datafile->data->Version, The comment is a bit redundant with the name of the function you are calling. I'd just omit the comment. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On Wed, 2014-10-08 at 12:33 +0200, Ján Tomko wrote: > On 10/07/2014 06:07 AM, Chen Fan wrote: > > Signed-off-by: Chen Fan > > --- > > src/libvirt_private.syms | 1 + > > src/qemu/qemu_conf.c | 50 > > > > src/qemu/qemu_conf.h | 2 ++ > > src/util/virsocketaddr.c | 24 +++ > > src/util/virsocketaddr.h | 2 ++ > > 5 files changed, 79 insertions(+) > > > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > > index 8ab1394..a104bc6 100644 > > --- a/src/libvirt_private.syms > > +++ b/src/libvirt_private.syms > > @@ -1911,6 +1911,7 @@ virSocketAddrGetIpPrefix; > > virSocketAddrGetPort; > > virSocketAddrGetRange; > > virSocketAddrIsNetmask; > > +virSocketAddrIsNumericLocalhost; > > virSocketAddrIsPrivate; > > virSocketAddrIsWildcard; > > virSocketAddrMask; > > diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c > > index adc6caf..6b0ac5c 100644 > > --- a/src/qemu/qemu_conf.c > > +++ b/src/qemu/qemu_conf.c > > @@ -707,6 +707,15 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr > > cfg, > > GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); > > > > GET_VALUE_STR("migration_host", cfg->migrateHost); > > +if (cfg->migrateHost && > > +qemuCheckLocalhost(cfg->migrateHost)) { > > +virReportError(VIR_ERR_CONF_SYNTAX, > > + _("migration_host must not be the address of" > > + " the local machine: %s"), > > + cfg->migrateHost); > > +goto cleanup; > > +} > > + > > GET_VALUE_STR("migration_address", cfg->migrationAddress); > > > > GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); > > @@ -1371,3 +1380,44 @@ qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, > > > > return qemuGetHugepagePath(&hugetlbfs[i]); > > } > > + > > +bool > > +qemuCheckLocalhost(const char *addrStr) > > +{ > > +virSocketAddr addr; > > +char *hostname, *tmp; > > +bool encloseAddress = false; > > +int family; > > +bool ret = true; > > + > > +if (VIR_STRDUP(hostname, addrStr) < 0) > > +return false; > > + > > +tmp = hostname; > > + > > +if (STRPREFIX(hostname, "[")) { > > +char *end = strchr(hostname, ']'); > > +if (end) { > > +*end = '\0'; > > +hostname++; > > +encloseAddress = true; > > +} > > +} > > We don't format the qemu.conf back and we don't need the brackets for > anything. We can just store the migration host without them in > cfg->migrationHost > > > + > > +if (STRPREFIX(hostname, "localhost")) > > +goto cleanup; > > + > > +family = virSocketAddrNumericFamily(hostname); > > +if ((family == AF_INET && !encloseAddress) || > > +family == AF_INET6) { > > +if (virSocketAddrParse(&addr, hostname, family) > 0 && > > +virSocketAddrIsNumericLocalhost(&addr)) { > > +goto cleanup; > > +} > > +} > > There's no need to check for family upfront. > > > + > > +ret = false; > > +cleanup: > > +VIR_FREE(tmp); > > +return ret; > > +} > > diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h > > index cb01fb6..c9ce53c 100644 > > --- a/src/qemu/qemu_conf.h > > +++ b/src/qemu/qemu_conf.h > > @@ -322,4 +322,6 @@ int qemuTranslateSnapshotDiskSourcePool(virConnectPtr > > conn, > > char * qemuGetHugepagePath(virHugeTLBFSPtr hugepage); > > char * qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, > >size_t nhugetlbfs); > > + > > +bool qemuCheckLocalhost(const char *addrStr); > > #endif /* __QEMUD_CONF_H */ > > diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c > > index 7fe7a15..6d36689 100644 > > --- a/src/util/virsocketaddr.c > > +++ b/src/util/virsocketaddr.c > > @@ -878,3 +878,27 @@ virSocketAddrNumericFamily(const char *address) > > freeaddrinfo(res); > > return family; > > } > > + > > +/** > > + * virSocketAddrIsNumericLocalhost: > > + * @address: address to check > > + * > > + * Check if passed address is a numeric 'localhost' address. > > + * > > + * Returns: true if @address is a numeric 'localhost' address, > > + * false otherwise > > + */ > > +bool > > +virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) > > I've rewritten this function to take a 'const char *' argument. > Along with the virStringStripIPv6Brackets function I've sent for review > separately, this removes the need for a separate qemuCheckLocalhost function > and it can be inlined. > > > +{ > > +struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; > > +switch (addr->data.stor.ss_family) { > > +case AF_INET: > > +return memcmp(&addr->data.inet4.sin_addr.s_addr, &tmp.s_addr, > > + sizeof(addr->data.inet4.sin_addr.s_addr)) == 0; > > +case AF_INET6: > > +return IN6_IS_ADDR_LOOPBACK(&addr->data.inet6.sin6_addr); > > +
[libvirt] [PATCH v3 7/7] qemu-attach: Assign device aliases
https://bugzilla.redhat.com/show_bug.cgi?id=1141621 As part of attach processing, assign the device aliases by calling qemuAssignDeviceAliases during qemuDomainQemuAttach once all the devices are found after the qemuParseCommandLinePid processing. This will alleviate a symptom that caused a libvirtd crash during an attempted device detach. Signed-off-by: John Ferlan --- src/qemu/qemu_driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4e2b356..57daa67 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14862,6 +14862,9 @@ static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn, if (qemuCanonicalizeMachine(def, qemuCaps) < 0) goto cleanup; +if (qemuAssignDeviceAliases(def, qemuCaps) < 0) +goto cleanup; + if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0) goto cleanup; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 4/7] hotplug: Check for alias in hostdev detach
If the QEMU_CAPS_DEVICE is set, then ensure the host device alias has been properly set before making the calls to detach the device Signed-off-by: John Ferlan --- src/qemu/qemu_hotplug.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 3e8cdbf..db39948 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3371,8 +3371,15 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr detach) { +qemuDomainObjPrivatePtr priv = vm->privateData; int ret = -1; +if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && +!detach->info->alias) { +if (qemuAssignDeviceHostdevAlias(vm->def, detach, -1) < 0) +return -1; +} + switch (detach->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: ret = qemuDomainDetachHostPCIDevice(driver, vm, detach); -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 1/7] virsh: Adjust the text in man page regarding qemu-attach
Slight adjustment to the qemu-attach man page to note device hotplug and hot unplug may not work and that the environment should be considered read-only Signed-off-by: John Ferlan --- tools/virsh.pod | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/virsh.pod b/tools/virsh.pod index eae9195..bd17f68 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -3698,8 +3698,9 @@ using the UNIX driver. Ideally the process will also have had the Not all functions of libvirt are expected to work reliably after attaching to an externally launched QEMU process. There may be -issues with the guest ABI changing upon migration, and hotunplug -may not work. +issues with the guest ABI changing upon migration and device hotplug +or hotunplug may not work. The attached environment should be considered +primarily read-only. =item B I { [I<--hmp>] | [I<--pretty>] } I... -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 5/7] hotplug: Check for alias in chrdev detach
If the QEMU_CAPS_DEVICE is set, then ensure the chr device alias has been properly set before making the calls to detach the device Signed-off-by: John Ferlan --- src/qemu/qemu_hotplug.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index db39948..f79a37a 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3696,6 +3696,12 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver, return ret; } +if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && +!tmpChr->info.alias) { +if (qemuAssignDeviceChrAlias(vmdef, tmpChr, -1) < 0) +return ret; +} + if (qemuBuildChrDeviceStr(&devstr, vm->def, chr, priv->qemuCaps) < 0) return ret; -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 0/7] hotplug: Fix libvirtd crash on qemu-attached guest
v2 is here: http://www.redhat.com/archives/libvir-list/2014-September/msg01575.html As Michal pointed out in his review - other devices could have the same issue - so take care of each of them separately (I already knew the answer to my last question...) Totally different approach this time - rather than error out, follow the example I from the Controller Detach code which will generate an alias for the device (although it did miss one minor check to see if it was already set leading to a potential memory leak since the alias code would overwrite whatever was there). Note: In a way 1/7 was already ACK'd - I just hadn't separated it yet for a push and wanted to keep these closer together when/if they were pushed. Whether 7/7 is now necessary is debateable - I keep it only for completeness and environment setup in much the same way the start code handles aliases. John Ferlan (7): virsh: Adjust the text in man page regarding qemu-attach hotplug: Check for alias in controller detach hotplug: Check for alias in disk detach hotplug: Check for alias in hostdev detach hotplug: Check for alias in chrdev detach hotplug: Check for alias in net detach qemu-attach: Assign device aliases src/qemu/qemu_driver.c | 3 +++ src/qemu/qemu_hotplug.c | 28 +++- tools/virsh.pod | 5 +++-- 3 files changed, 33 insertions(+), 3 deletions(-) -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 6/7] hotplug: Check for alias in net detach
https://bugzilla.redhat.com/show_bug.cgi?id=1141621 If the QEMU_CAPS_DEVICE is set, then ensure the host device alias has been properly set before making the calls to detach the device Signed-off-by: John Ferlan --- src/qemu/qemu_hotplug.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index f79a37a..33241fb 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3530,6 +3530,12 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver, } } +if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && +!detach->info.alias) { +if (qemuAssignDeviceNetAlias(vm->def, detach, -1) < 0) +goto cleanup; +} + qemuDomainMarkDeviceForRemoval(vm, &detach->info); qemuDomainObjEnterMonitor(driver, vm); -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 3/7] hotplug: Check for alias in disk detach
If the QEMU_CAPS_DEVICE is set, then ensure the disk device alias has been properly set in prior to making the calls to detach the device. Signed-off-by: John Ferlan --- src/qemu/qemu_hotplug.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 9c0f6c9..3e8cdbf 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2998,6 +2998,12 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver, } } +if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && +!detach->info.alias) { +if (qemuAssignDeviceDiskAlias(vm->def, detach, priv->qemuCaps) < 0) +goto cleanup; +} + qemuDomainMarkDeviceForRemoval(vm, &detach->info); qemuDomainObjEnterMonitor(driver, vm); -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 2/7] hotplug: Check for alias in controller detach
In qemuDomainDetachControllerDevice if the info.alias already exists a call to qemuAssignDeviceControllerAlias would overwrite the existing so avoid this possibility. Signed-off-by: John Ferlan --- src/qemu/qemu_hotplug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 1e504ec..9c0f6c9 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3226,7 +3226,8 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver, goto cleanup; } -if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { +if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) && +!detach->info.alias) { if (qemuAssignDeviceControllerAlias(detach) < 0) goto cleanup; } -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/2] network: Add code for setting network bandwidth for ethernet interfaces
On 10/8/14, 2:39 PM, "Eric Blake" wrote: >On 10/08/2014 01:59 PM, Anirban Chakraborty wrote: >> >> Signed-off-by: Anirban Chakraborty >> --- >> src/conf/domain_conf.h | 3 ++- >> 1 file changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h >> index f03599e..91da1ec 100644 >> --- a/src/conf/domain_conf.h >> +++ b/src/conf/domain_conf.h >> @@ -2852,7 +2852,8 @@ static inline bool virNetDevSupportBandwidth(int >>type) >> { >> return ((type == VIR_DOMAIN_NET_TYPE_BRIDGE || >> type == VIR_DOMAIN_NET_TYPE_NETWORK || >> - type == VIR_DOMAIN_NET_TYPE_DIRECT) ? true : false); >> + type == VIR_DOMAIN_NET_TYPE_DIRECT || >> + type == VIR_DOMAIN_NET_TYPE_ETHERNET) ? true : false); > >Needs rework after my comments on 1/2. I also wonder if this should >just be folded in to that patch, and/or made into a switch statement >where the compiler forces us to think about any future >VIR_DOMAIN_NET_TYPE_* additions on whether they should return true or >false. I will rework the 1/2 patch to fix syntax etc. Initially, I sent a single patch to keep everything together, however, there was a suggestion to split it. I decided to split it into two as clearly there are two parts to this series, one to prepare the code for addition of ethernet interfaces and the other to add the ethernet type. True, the second patch is very minimal and I can fold it back into a single patch if everyone agrees to it. > >As in: > >bool virNetDevSupportBandwidth(virDomainNetType type) >{ >switch (type) { >case VIR_DOMAIN_NET_TYPE_BRIDGE: >case VIR_DOMAIN_NET_TYPE_NETWORK: >case VIR_DOMAIN_NET_TYPE_DIRECT: >case VIR_DOMAIN_NET_TYPE_ETHERNET: >return true; >case VIR_DOMAIN_NET_TYPE_USER: >case VIR_DOMAIN_NET_TYPE_VHOSTUSER: >case VIR_DOMAIN_NET_TYPE_SERVER: >case VIR_DOMAIN_NET_TYPE_CLIENT: >case VIR_DOMAIN_NET_TYPE_MCAST: >case VIR_DOMAIN_NET_TYPE_INTERNAL: >case VIR_DOMAIN_NET_TYPE_HOSTDEV: >case VIR_DOMAIN_NET_TYPE_LAST: >/* cover all enums to appease the compiler */ ; >} >return false; >} We could have the function defined with a switch, however, instead of listing all the types, I could return false from the default case. Something like: switch (type) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_DIRECT: case VIR_DOMAIN_NET_TYPE_ETHERNET: return true; default; return false; } Will this work for you? Thanks. -Anirban -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 02/21] Added implementation for virConnectGetVersion (required CIM_DataFile class)
On 10/08/2014 06:33 AM, Yves Vinter wrote: > From: yvinter Looks like you had identity problems throughout the series. I don't mind touching up first-time contributions, but it would be nice to get it right in the future so I don't have to spend time on it. > > --- > src/hyperv/hyperv_driver.c| 55 > +++ > src/hyperv/hyperv_wmi_generator.input | 37 +++ > src/hyperv/hyperv_wmi_generator.py| 4 +-- > 3 files changed, 94 insertions(+), 2 deletions(-) > > diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c > index 372ff39..f2017c3 100644 > --- a/src/hyperv/hyperv_driver.c > +++ b/src/hyperv/hyperv_driver.c > @@ -1232,6 +1232,7 @@ hypervDomainManagedSaveRemove(virDomainPtr domain, > unsigned int flags) > } > > > + > #define MATCH(FLAG) (flags & (FLAG)) Why the added blank line? > static int > hypervConnectListAllDomains(virConnectPtr conn, > @@ -1366,6 +1367,59 @@ hypervConnectListAllDomains(virConnectPtr conn, > > > > +static int Wow, that's a lot of blank lines already there. > +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) > +{ > +int result = -1; > +hypervPrivate *priv = conn->privateData; > +CIM_DataFile *datafile = NULL; Why the double space? > +virBuffer query = VIR_BUFFER_INITIALIZER; > +char *p; > + > +virBufferAddLit(&query, " Select * from CIM_DataFile where > Name='c:windowssystem32vmms.exe' "); Is the leading and trailing space really necessary in the string literal? > +if (hypervGetCIMDataFileList(priv, &query, &datafile) < 0) { > +goto cleanup; > +} Libvirt style says {} are not necessary for one-line bodies (qemu style would require it, but we're a bit more lenient). > + > +/* Check the result of convertion */ > +if (datafile == NULL) { It's sufficient to write 'if (datafile)' (comparison to NULL is just extra verbosity); but as that appears to be the prevailing style already in this file, I'm not going to worry about shortening it. > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not lookup %s for domain %s"), > + "Msvm_VirtualSystemSettingData", > + datafile->data->Version); > +goto cleanup; > +} > + > +/* Delete release number and last digit of build number 1.1.111x. */ > +p = strrchr(datafile->data->Version,'.'); This failed 'make syntax-check' due to a missing space: GEN bracket-spacing-check src/hyperv/hyperv_driver.c:1381: p = strrchr(datafile->data->Version,'.'); maint.mk: incorrect whitespace, see HACKING for rules make: *** [bracket-spacing-check] Error 1 > +if (p == NULL) { > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not parse version number from '%s'"), > + datafile->data->Version); > +goto cleanup; > +} > +p--; > +*p = '\0'; > + > +/* Parse Version String to Long */ > +if (virParseVersionString(datafile->data->Version, > + version, true) < 0) { > +virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Could not parse version number from '%s'"), > + datafile->data->Version); > +goto cleanup; > +} > + > +result = 0; > + > + cleanup: > +hypervFreeObject(priv, (hypervObject *)datafile); > +virBufferFreeAndReset(&query); This line is not necessary if you ACK my v2 of 1/21. > + > +return result; > +} > + > + > > static virDriver hypervDriver = { > .no = VIR_DRV_HYPERV, > @@ -1402,6 +1456,7 @@ static virDriver hypervDriver = { > .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ > .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ > .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ > +.connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ > }; I got through here in my review for now; mostly looks good other than style. When I finish the rest of the patch, I may end up just fixing it myself and pushing. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/2] network: Add code for setting network bandwidth for ethernet interfaces
On 10/08/2014 01:59 PM, Anirban Chakraborty wrote: > > Signed-off-by: Anirban Chakraborty > --- > src/conf/domain_conf.h | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index f03599e..91da1ec 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -2852,7 +2852,8 @@ static inline bool virNetDevSupportBandwidth(int type) > { > return ((type == VIR_DOMAIN_NET_TYPE_BRIDGE || > type == VIR_DOMAIN_NET_TYPE_NETWORK || > - type == VIR_DOMAIN_NET_TYPE_DIRECT) ? true : false); > + type == VIR_DOMAIN_NET_TYPE_DIRECT || > + type == VIR_DOMAIN_NET_TYPE_ETHERNET) ? true : false); Needs rework after my comments on 1/2. I also wonder if this should just be folded in to that patch, and/or made into a switch statement where the compiler forces us to think about any future VIR_DOMAIN_NET_TYPE_* additions on whether they should return true or false. As in: bool virNetDevSupportBandwidth(virDomainNetType type) { switch (type) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: case VIR_DOMAIN_NET_TYPE_DIRECT: case VIR_DOMAIN_NET_TYPE_ETHERNET: return true; case VIR_DOMAIN_NET_TYPE_USER: case VIR_DOMAIN_NET_TYPE_VHOSTUSER: case VIR_DOMAIN_NET_TYPE_SERVER: case VIR_DOMAIN_NET_TYPE_CLIENT: case VIR_DOMAIN_NET_TYPE_MCAST: case VIR_DOMAIN_NET_TYPE_INTERNAL: case VIR_DOMAIN_NET_TYPE_HOSTDEV: case VIR_DOMAIN_NET_TYPE_LAST: /* cover all enums to appease the compiler */ ; } return false; } -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 1/2] network: Refactor code to add bandwidth support for ethernet interfaces
On 10/08/2014 01:55 PM, Anirban Chakraborty wrote: > Modified code to set and clear bandwidth cleanly. [meta-comment - this mail wasn't threaded to the 0/2 cover letter, but came through as its own top-level thread. This makes it harder to track the series] > > Signed-off-by: Anirban Chakraborty > --- > src/conf/domain_conf.h | 7 +++ > src/lxc/lxc_driver.c| 3 +++ > src/lxc/lxc_process.c | 18 +- > src/qemu/qemu_command.c | 25 +++-- > src/qemu/qemu_command.h | 2 ++ > src/qemu/qemu_driver.c | 3 +++ > src/qemu/qemu_hotplug.c | 12 > src/qemu/qemu_process.c | 3 +++ > src/util/virnetdevmacvlan.c | 10 -- > src/util/virnetdevmacvlan.h | 1 - > 10 files changed, 58 insertions(+), 26 deletions(-) Style review (I'll leave the content review to someone a bit more familiar with network code) > > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index afa3da6..f03599e 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -2848,4 +2848,11 @@ int virDomainObjSetMetadata(virDomainObjPtr vm, > bool virDomainDefNeedsPlacementAdvice(virDomainDefPtr def) > ATTRIBUTE_NONNULL(1); > > +static inline bool virNetDevSupportBandwidth(int type) > +{ > +return ((type == VIR_DOMAIN_NET_TYPE_BRIDGE || > + type == VIR_DOMAIN_NET_TYPE_NETWORK || > + type == VIR_DOMAIN_NET_TYPE_DIRECT) ? true : false); I think 'return cond ? true : false;' is a waste of source code. Just 'return cond;'. Indentation looks awkward; I would have done it: return (type == VIR_DOMAIN_NET_TYPE_BRIDGE || type == VIR_DOMAIN_NET_TYPE_NETWORK || type == VIR_DOMAIN_NET_TYPE_DIRECT); > +}; Spurious semicolon. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] NBD TLS support in QEMU
On Thu, Oct 02, 2014 at 03:50:57PM +0200, Wouter Verhelst wrote: > On Thu, Oct 02, 2014 at 01:00:04PM +0200, Paolo Bonzini wrote: > > Il 01/10/2014 22:23, Wouter Verhelst ha scritto: > > > Hi, > > > > > > On Fri, Sep 05, 2014 at 03:26:09PM +0200, Wouter Verhelst wrote: > > >> Tunneling the entire protocol inside an SSL connection doesn't fix that; > > >> if an attacker is able to hijack your TCP connections and change flags, > > >> then this attacker is also able to hijack your TCP connection and > > >> redirect it to a decrypting/encrypting proxy. > > >> > > >> I agree that preventing a possible SSL downgrade attack (and other forms > > >> of MITM) should be high on the priority list, but "tunnel the whole > > >> thing in SSL" doesn't do that. > > > > > > So, having given this some thought, I wanted to come up with a spec just > > > so that we had something we could all agree on. As part of that, I had a > > > look at qemu-nbd, and noticed that it uses the "oldstyle" handshake > > > protocol (on port 10809 by default -- ew, please don't do that). > > > > Can you use new-style handshake with a single unnamed export? Export > > names are a useless complication for qemu-nbd. > > Not currently, but I don't think you need that. You could have a default > name, which would be used if no name was otherwise specified. It's not > much of a stretch to make that name part of the protocol spec, either. So. I think this makes sense, and as such changed the proto.txt file as follows: diff --git a/doc/proto.txt b/doc/proto.txt index e0a4fb1..990d012 100644 --- a/doc/proto.txt +++ b/doc/proto.txt @@ -242,10 +242,13 @@ Option types * NBD_OPT_EXPORT_NAME (1) Choose the export which the client would like to use, and end option haggling. Data: name of the export, free-form UTF8 text (subject to limitations by server implementation). If the chosen export does not exist, the server closes the connection. + A special, "empty", name (i.e., the length field is zero and no name + is specified), is reserved for a "default" export, to be used in cases + where explicitly specifying an export name makes no sense. * NBD_OPT_ABORT (2) Abort negotiation and close the connection. Optional. * NBD_OPT_LIST (3) That is, specify an empty name to specify a default. Thoughts? -- It is easy to love a country that is famous for chocolate and beer -- Barack Obama, speaking in Brussels, Belgium, 2014-03-26 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] hotplug: Fix libvirtd crash on qemu-attached guest
On 10/08/2014 12:08 PM, Michal Privoznik wrote: > On 25.09.2014 17:00, John Ferlan wrote: >> https://bugzilla.redhat.com/show_bug.cgi?id=1141621 >> >> The crash in this case was because the qemu-attach code did not create >> aliases for qemu cli args. When the detach-interface code was called >> it assumed aliases were set resulting in a core when dereferencing the >> still NULL alias. >> >> Adding a call to qemuAssignDeviceAliases() resolves the path for >> qemu-attach; however, to prevent future issues an additional check >> for a NULL value is made and an error provided in the deatch path. >> >> Add some more verbiage to the virsh man page. >> >> Signed-off-by: John Ferlan >> --- >> >> v1 is here: >> http://www.redhat.com/archives/libvir-list/2014-September/msg01331.html >> >> Changes since v1: >> - Add the call to qemuAssignDeviceAliases() in qemuDomainQemuAttach(). >> - Move the check for NULL alias inside the CAPS_DEVICE check and emit >> an error rather than trying to remove as an "else" condition. >> >> src/qemu/qemu_driver.c | 3 +++ >> src/qemu/qemu_hotplug.c | 7 +++ >> tools/virsh.pod | 5 +++-- >> 3 files changed, 13 insertions(+), 2 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index 117138a..ef4ecd2 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -14746,6 +14746,9 @@ static virDomainPtr >> qemuDomainQemuAttach(virConnectPtr conn, >> if (qemuCanonicalizeMachine(def, qemuCaps) < 0) >> goto cleanup; >> >> +if (qemuAssignDeviceAliases(def, qemuCaps) < 0) >> +goto cleanup; >> + >> if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0) >> goto cleanup; >> >> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c >> index d631887..daebe82 100644 >> --- a/src/qemu/qemu_hotplug.c >> +++ b/src/qemu/qemu_hotplug.c >> @@ -3521,6 +3521,13 @@ qemuDomainDetachNetDevice(virConnectPtr conn, >> >> qemuDomainObjEnterMonitor(driver, vm); >> if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { >> +if (!detach->info.alias) { >> +virReportError(VIR_ERR_OPERATION_FAILED, "%s", >> + _("device alias not found: cannot delete the " >> + "net device")); >> +qemuDomainObjExitMonitor(driver, vm); >> +goto cleanup; >> +} > > Is there a reason to not check this upfront rather than this late in the > process? And I don't think that net devices are the only thing affected > here. For instance a virtio disks seems vulnerable too (well, at first > glance on the code). > Recall the environment - 'qemu-attach' and the bz... The bz is specific for network attach/detach, so I wasn't considering disks, controllers, hostdevs, and chrdevs when first working through this particular problem. Although based on some follow-up work (more in a bit) I've learned a bit more! Note that the check is specific to when the CAPS_DEVICE is set (IOW, using the newer device naming syntax). In this case, someone used -net/-net instead of -netdev/-device and the assumption in the code once we get to this point that the alias would filled in which without the qemuAssignDeviceAliases in qemuDomainQemuAttach wouldn't be the case. A side note is that qemuParseCommandLine() which is what qemu-attach will use when parsing the command line of the pid that's being attached to doesn't even handle -netdev, but that's a different issue. Anyway, even though the alias is there "now" the concern was the effect if some other path called into here without the alias. Since it only mattered when CAPS_DEVICE was set, that's why the check is where it is. The question relating to why not in some other caller is valid; however, not fool proof since none of the qemuDomainDetach* API's in qemu_hotplug.c are static. Making the check earlier in the caller of all those API's qemuDomainDetachDeviceLive is possible, but would have to avoid the check for DEVICE_LEASE since it doesn't use info.alias. As for disks (and perhaps other devices) - funny you should mention that... There's another bz (844845) that I have some patches I'm working on which actually allow a qemu using the 'id="drive-"' to work. As of now, starting qemu using the "id=" instead of "index=" will not allow the qemu-attach to succeed. And yes, I do believe given what I now know about the code, sure the disk, controller, hostdev, and chrdev paths could all be affected by the assumption of info.alias being set (although I don't have working examples of such a detachment). This is the long winded way of noting yes, it's possible; however, the example or bz doesn't exist. I can use this opportunity to make those checks (in much the same manner) if desired though... Also I'd need to know if there should be a separate patch for each (turning a 1 patch change into 5 or 6). John >> if (qemuMonitorDelDevice(priv->mon, detach->info.al
Re: [libvirt] [PATCH 2/2] qemu: change macvtap multicast list in response to NIC_RX_FILTER_CHANGED
On 10/08/2014 03:15 PM, Laine Stump wrote: On 10/06/2014 05:37 PM, akrow...@linux.vnet.ibm.com wrote: From: Tony Krowiak This patch adds functionality to processNicRxFilterChangedEvent(). The old and new multicast lists are compared and the filters in the macvtap are programmed to match the guest's filters. Signed-off-by: Tony Krowiak --- src/qemu/qemu_driver.c | 138 +++ 1 files changed, 114 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4e2b356..7ff9c38 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4147,6 +4147,106 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver, static void +syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter, + virNetDevRxFilterPtr hostFilter) +{ +char newMacStr[VIR_MAC_STRING_BUFLEN]; + +if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) { +virMacAddrFormat(&guestFilter->mac, newMacStr); + +/* set new MAC address from guest to associated macvtap device */ +if (virNetDevSetMAC(ifname, &guestFilter->mac)) { +VIR_WARN("Couldn't set new MAC address %s to device %s " + "while responding to NIC_RX_FILTER_CHANGED", + newMacStr, ifname); +} else { +VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr); +} +} +} + + +static void +syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter, + virNetDevRxFilterPtr hostFilter) +{ +size_t i, j; +bool found; +char macstr[VIR_MAC_STRING_BUFLEN]; + +for (i = 0; i < guestFilter->multicast.nTable; i++) { +found = false; + +for (j = 0; j < hostFilter->multicast.nTable; j++) { +if (virMacAddrCmp(&guestFilter->multicast.table[i], + &hostFilter->multicast.table[j]) == 0) { +found = true; +break; +} +} + +if (!found) { +virMacAddrFormat(&guestFilter->multicast.table[i], macstr); + +if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i])) { +VIR_WARN("Couldn't add new multicast MAC address %s to " + "device %s while responding to NIC_RX_FILTER_CHANGED", + macstr, ifname); +} else { +VIR_DEBUG("Added multicast MAC %s to %s interface", + macstr, ifname); +} +} +} +} + + +static void +syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter, + virNetDevRxFilterPtr hostFilter) +{ +size_t i, j; +bool found; +char macstr[VIR_MAC_STRING_BUFLEN]; + +for (i = 0; i < hostFilter->multicast.nTable; i++) { +found = false; + +for (j = 0; j < guestFilter->multicast.nTable; j++) { +if (virMacAddrCmp(&hostFilter->multicast.table[i], + &guestFilter->multicast.table[j]) == 0) { +found = true; +break; +} +} + +if (!found) { +virMacAddrFormat(&hostFilter->multicast.table[i], macstr); + +if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i])) { +VIR_WARN("Couldn't delete multicast MAC address %s from " + "device %s while responding to NIC_RX_FILTER_CHANGED", + macstr, ifname); +} else { +VIR_DEBUG("Deleted multicast MAC %s from %s interface", + macstr, ifname); +} +} +} +} + + +static void +syncNicRxFilterMulticast(char *ifname, + virNetDevRxFilterPtr guestFilter, + virNetDevRxFilterPtr hostFilter) +{ +syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter); +syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter); Interesting method. I had planned to sort both lists, then do a single loop that went through the two in parallel, deleting/adding from the host interface filter at each step as necessary. Yours works, too, though. :-) ACK to this patch. I'll push it along with 1/2 once a new eversion of that patch has gotten ACK. BTW, once we're programming the multicast filter, do we need to set any other mode of the macvtap device in order for this to have a positive impact on performance? Or does multicast simply not work properly without this patch (I don't use multicast for anything, and don't have any tests setup to use multicast). To be honest, the only testing I did was to make sure that if I added or deleted a multicast MAC on the guest, that it showed up in the macvtap list on the host. I am not too networking literate and rely on our system test team to flesh out those issues. The next thing on my
[libvirt] [PATCH v3 2/2] network: Add code for setting network bandwidth for ethernet interfaces
Signed-off-by: Anirban Chakraborty --- src/conf/domain_conf.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f03599e..91da1ec 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2852,7 +2852,8 @@ static inline bool virNetDevSupportBandwidth(int type) { return ((type == VIR_DOMAIN_NET_TYPE_BRIDGE || type == VIR_DOMAIN_NET_TYPE_NETWORK || - type == VIR_DOMAIN_NET_TYPE_DIRECT) ? true : false); + type == VIR_DOMAIN_NET_TYPE_DIRECT || + type == VIR_DOMAIN_NET_TYPE_ETHERNET) ? true : false); }; #endif /* __DOMAIN_CONF_H */ -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 1/2] network: Refactor code to add bandwidth support for ethernet interfaces
Modified code to set and clear bandwidth cleanly. Signed-off-by: Anirban Chakraborty --- src/conf/domain_conf.h | 7 +++ src/lxc/lxc_driver.c| 3 +++ src/lxc/lxc_process.c | 18 +- src/qemu/qemu_command.c | 25 +++-- src/qemu/qemu_command.h | 2 ++ src/qemu/qemu_driver.c | 3 +++ src/qemu/qemu_hotplug.c | 12 src/qemu/qemu_process.c | 3 +++ src/util/virnetdevmacvlan.c | 10 -- src/util/virnetdevmacvlan.h | 1 - 10 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index afa3da6..f03599e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2848,4 +2848,11 @@ int virDomainObjSetMetadata(virDomainObjPtr vm, bool virDomainDefNeedsPlacementAdvice(virDomainDefPtr def) ATTRIBUTE_NONNULL(1); +static inline bool virNetDevSupportBandwidth(int type) +{ +return ((type == VIR_DOMAIN_NET_TYPE_BRIDGE || + type == VIR_DOMAIN_NET_TYPE_NETWORK || + type == VIR_DOMAIN_NET_TYPE_DIRECT) ? true : false); +}; + #endif /* __DOMAIN_CONF_H */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index b3e506f..a6f1f8a 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -72,6 +72,7 @@ #include "viraccessapicheck.h" #include "viraccessapichecklxc.h" #include "virhostdev.h" +#include "qemu/qemu_command.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -4634,6 +4635,8 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm, detach = vm->def->nets[detachidx]; +qemuDomainClearNetBandwidth(vm); + switch (virDomainNetGetActualType(detach)) { case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_NETWORK: diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index ed30c37..3192011 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -274,11 +274,6 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn, if (virNetDevSetOnline(parentVeth, true) < 0) goto cleanup; -if (virNetDevBandwidthSet(net->ifname, - virDomainNetGetActualBandwidth(net), - false) < 0) -goto cleanup; - if (net->filter && virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0) goto cleanup; @@ -300,6 +295,7 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, virNetDevBandwidthPtr bw; virNetDevVPortProfilePtr prof; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); +const char *linkdev = virDomainNetGetActualDirectDev(net); /* XXX how todo bandwidth controls ? * Since the 'net-ifname' is about to be moved to a different @@ -329,14 +325,13 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, if (virNetDevMacVLanCreateWithVPortProfile( net->ifname, &net->mac, -virDomainNetGetActualDirectDev(net), +linkdev, virDomainNetGetActualDirectMode(net), false, def->uuid, -virDomainNetGetActualVirtPortProfile(net), +prof, &res_ifname, VIR_NETDEV_VPORT_PROFILE_OP_CREATE, -cfg->stateDir, -virDomainNetGetActualBandwidth(net), 0) < 0) +cfg->stateDir, 0) < 0) goto cleanup; ret = res_ifname; @@ -450,6 +445,11 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, goto cleanup; } +/* set network bandwidth */ +if (virNetDevBandwidthSet(def->nets[i]->ifname, +virDomainNetGetActualBandwidth(def->nets[i]), false) < 0) + goto cleanup; + (*veths)[(*nveths)-1] = veth; /* Make sure all net definitions will have a name in the container */ diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8cb0865..3635712 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -191,7 +191,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def, virDomainNetGetActualVirtPortProfile(net), &res_ifname, vmop, cfg->stateDir, -virDomainNetGetActualBandwidth(net), macvlan_create_flags); if (rc >= 0) { virDomainAuditNetDevice(def, net, res_ifname, true); @@ -371,11 +370,6 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, &net->mac) < 0) goto cleanup; -if (virNetDevBandwidthSet(net->ifname, - virDomainNetGetActualBandwidth(net), - false) < 0) -goto cleanup; - if (net->filter && virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) { goto cleanup; @@ -7427,6 +7421,13 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd, goto cleanup; } +/* Set Bandwidth */ +if (virNetDevSupportBandwidth(actualType) && + virNetDevBandwidthSet(net->ifname, + virDomainNetGetActualBandwidth(net), +
[libvirt] [PATCH v3 0/2] network: Add network bandwidth for ethernet type interfaces
V3: Addressed issues pointed out in V2 Split into two patches V2: Addressed comments raised in review of V1. Consolidate calls to virNetDevBandwidthSet. Clear bandwidth settings when the interface is detached or domain destroyed. V1: Ethernet interfaces in libvirt currently do not support bandwidth setting. For example, following xml file for an interface will not apply these settings to corresponding qdiscs. Signed-off-by: Anirban Chakraborty Anirban Chakraborty (2): network: Refactor code to add bandwidth support for ethernet interfaces network: Add code for setting bandwidth for ethernet interfaces src/conf/domain_conf.h | 8 src/lxc/lxc_driver.c| 3 +++ src/lxc/lxc_process.c | 18 +- src/qemu/qemu_command.c | 25 +++-- src/qemu/qemu_command.h | 2 ++ src/qemu/qemu_driver.c | 3 +++ src/qemu/qemu_hotplug.c | 12 src/qemu/qemu_process.c | 3 +++ src/util/virnetdevmacvlan.c | 10 -- src/util/virnetdevmacvlan.h | 1 - 10 files changed, 59 insertions(+), 26 deletions(-) -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] qemu: change macvtap multicast list in response to NIC_RX_FILTER_CHANGED
On 10/06/2014 05:37 PM, akrow...@linux.vnet.ibm.com wrote: > From: Tony Krowiak > > This patch adds functionality to processNicRxFilterChangedEvent(). > The old and new multicast lists are compared and the filters in > the macvtap are programmed to match the guest's filters. > > Signed-off-by: Tony Krowiak > --- > src/qemu/qemu_driver.c | 138 +++ > 1 files changed, 114 insertions(+), 24 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 4e2b356..7ff9c38 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -4147,6 +4147,106 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver, > > > static void > +syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter, > + virNetDevRxFilterPtr hostFilter) > +{ > +char newMacStr[VIR_MAC_STRING_BUFLEN]; > + > +if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) { > +virMacAddrFormat(&guestFilter->mac, newMacStr); > + > +/* set new MAC address from guest to associated macvtap device */ > +if (virNetDevSetMAC(ifname, &guestFilter->mac)) { > +VIR_WARN("Couldn't set new MAC address %s to device %s " > + "while responding to NIC_RX_FILTER_CHANGED", > + newMacStr, ifname); > +} else { > +VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr); > +} > +} > +} > + > + > +static void > +syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter, > + virNetDevRxFilterPtr hostFilter) > +{ > +size_t i, j; > +bool found; > +char macstr[VIR_MAC_STRING_BUFLEN]; > + > +for (i = 0; i < guestFilter->multicast.nTable; i++) { > +found = false; > + > +for (j = 0; j < hostFilter->multicast.nTable; j++) { > +if (virMacAddrCmp(&guestFilter->multicast.table[i], > + &hostFilter->multicast.table[j]) == 0) { > +found = true; > +break; > +} > +} > + > +if (!found) { > +virMacAddrFormat(&guestFilter->multicast.table[i], macstr); > + > +if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i])) > { > +VIR_WARN("Couldn't add new multicast MAC address %s to " > + "device %s while responding to > NIC_RX_FILTER_CHANGED", > + macstr, ifname); > +} else { > +VIR_DEBUG("Added multicast MAC %s to %s interface", > + macstr, ifname); > +} > +} > +} > +} > + > + > +static void > +syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter, > + virNetDevRxFilterPtr hostFilter) > +{ > +size_t i, j; > +bool found; > +char macstr[VIR_MAC_STRING_BUFLEN]; > + > +for (i = 0; i < hostFilter->multicast.nTable; i++) { > +found = false; > + > +for (j = 0; j < guestFilter->multicast.nTable; j++) { > +if (virMacAddrCmp(&hostFilter->multicast.table[i], > + &guestFilter->multicast.table[j]) == 0) { > +found = true; > +break; > +} > +} > + > +if (!found) { > +virMacAddrFormat(&hostFilter->multicast.table[i], macstr); > + > +if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i])) { > +VIR_WARN("Couldn't delete multicast MAC address %s from " > + "device %s while responding to > NIC_RX_FILTER_CHANGED", > + macstr, ifname); > +} else { > +VIR_DEBUG("Deleted multicast MAC %s from %s interface", > + macstr, ifname); > +} > +} > +} > +} > + > + > +static void > +syncNicRxFilterMulticast(char *ifname, > + virNetDevRxFilterPtr guestFilter, > + virNetDevRxFilterPtr hostFilter) > +{ > +syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter); > +syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter); Interesting method. I had planned to sort both lists, then do a single loop that went through the two in parallel, deleting/adding from the host interface filter at each step as necessary. Yours works, too, though. :-) ACK to this patch. I'll push it along with 1/2 once a new eversion of that patch has gotten ACK. BTW, once we're programming the multicast filter, do we need to set any other mode of the macvtap device in order for this to have a positive impact on performance? Or does multicast simply not work properly without this patch (I don't use multicast for anything, and don't have any tests setup to use multicast). > +} > + > +static void > processNicRxFilterChangedEvent(virQEMUDriverPtr driver, >
Re: [libvirt] [PATCH 1/2] util: Functions to update host network device's multicast filter
On 10/08/2014 01:41 PM, Tony Krowiak wrote: >> Otherwise it looks okay. As we've discussed, it would be nice to use >> netlink instead of /proc/net and ioctl(), but that can be added later. > I agree. When I originally started working on this, that was my plan, > however; after spending days trying to understand how to use netlink > to do retrieve the multicast list, I gave up when I found that > iproute2 does it by reading the file. Can you point me to some good, > detailed netlink documentation? I've googled for it, looked at code > examples and experimented by writing code snippets and have not been > able to figure out how to retrieve the multicast list using netlink. No :-( That is a *big* problem with netlink, and I went through the same journey as you (although probably spent less time, as you sent your first message when I'd only been looking at it for a day or so). I *think* there is a libnl cache that can be used to retrieve the multicast list (look for the libnl-devel mailing list archives for a message I sent there several days ago, along with a couple of responses), but it's definitely not as straightforward as reading a file in /proc. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/2] util: Functions to update host network device's multicast filter
On 10/08/2014 11:36 AM, Laine Stump wrote: On 10/06/2014 05:37 PM, akrow...@linux.vnet.ibm.com wrote: From: Tony Krowiak This patch provides the utility functions to needed to synchronize the changes made to a guest domain network device's multicast filter with the corresponding macvtap device's filter on the host: * Get/add/remove multicast MAC addresses * Get the macvtap device's RX filter list Signed-off-by: Tony Krowiak --- src/libvirt_private.syms |4 + src/util/virmacaddr.c| 37 + src/util/virmacaddr.h|4 + src/util/virnetdev.c | 360 ++ src/util/virnetdev.h | 11 ++ 5 files changed, 416 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d6265ac..6d06a2c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1590,13 +1590,16 @@ virMacAddrIsBroadcastRaw; virMacAddrIsMulticast; virMacAddrIsUnicast; virMacAddrParse; +virMacAddrParseHex; virMacAddrSet; virMacAddrSetRaw; # util/virnetdev.h +virNetDevAddMulti; virNetDevAddRoute; virNetDevClearIPv4Address; +virNetDevDelMulti; virNetDevExists; virNetDevGetIndex; virNetDevGetIPv4Address; @@ -1604,6 +1607,7 @@ virNetDevGetLinkInfo; virNetDevGetMAC; virNetDevGetMTU; virNetDevGetPhysicalFunction; +virNetDevGetRxFilter; virNetDevGetVirtualFunctionIndex; virNetDevGetVirtualFunctionInfo; virNetDevGetVirtualFunctions; diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c index ebd1182..ae5e5d2 100644 --- a/src/util/virmacaddr.c +++ b/src/util/virmacaddr.c @@ -198,6 +198,43 @@ virMacAddrFormat(const virMacAddr *addr, return str; } +/** + * virMacAddrParseHex: + * @str: string hexadecimal representation of MAC address, e.g., "F801EFCE3aCB" + * @addr: 6-byte MAC address + * + * Parse the hexadecimal representation of a MAC address + * + * Return 0 upon success, or -1 in case of error. + */ +int +virMacAddrParseHex(const char* str, virMacAddrPtr addr) +{ +if (strlen(str) != VIR_MAC_HEXLEN) +return -1; + +size_t iaddr; +size_t istr; + + +for (istr = 0, iaddr = 0; iaddr < VIR_MAC_BUFLEN; istr += 2, iaddr++) { +unsigned int hex; + +if (sscanf(&str[istr], "%02x", &hex) != 1) +break; I'm not keen on sscanf(), but since we're already using it elsewhere, and the existing virMacAddrParse uses the normally-blacklisted strtoul() (and using virStrToLong_ui() on pieces of the string would require a terminating character after each piece), I don't have a ready answer for an alternative. Eric, do you have an opinion on this? Is sscanf okay when we want to parse: of hex digits into 6 binary bytes? See my response to Eric's response. + +if (hex > UCHAR_MAX) +break; + +addr->addr[iaddr] = hex; +} + +if (istr == VIR_MAC_HEXLEN) +return 0; + +return -1; +} + void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN], virMacAddrPtr addr) { diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h index 49efc36..72a285a 100644 --- a/src/util/virmacaddr.h +++ b/src/util/virmacaddr.h @@ -27,6 +27,7 @@ # include "internal.h" # define VIR_MAC_BUFLEN 6 +#define VIR_MAC_HEXLEN (VIR_MAC_BUFLEN * 2) # define VIR_MAC_PREFIX_BUFLEN 3 # define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) @@ -50,6 +51,9 @@ void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN], virMacAddrPtr addr); int virMacAddrParse(const char* str, virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK; +int virMacAddrParseHex(const char* str, + virMacAddrPtr addr) +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; bool virMacAddrIsUnicast(const virMacAddr *addr); bool virMacAddrIsMulticast(const virMacAddr *addr); bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]); diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index db5623a..5e53f5f 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -56,6 +56,33 @@ VIR_LOG_INIT("util.netdev"); +# define VIR_MCAST_NAME_LEN (IFNAMSIZ + 1) +# define VIR_MCAST_INDEX_TOKEN_IDX 0 +# define VIR_MCAST_NAME_TOKEN_IDX 1 +# define VIR_MCAST_USERS_TOKEN_IDX 2 +# define VIR_MCAST_GLOBAL_TOKEN_IDX 3 +# define VIR_MCAST_ADDR_TOKEN_IDX 4 +# define VIR_MCAST_NUM_TOKENS 5 +# define VIR_MCAST_TOKEN_DELIMS " \n" +# define VIR_MCAST_ADDR_LEN (VIR_MAC_HEXLEN + 1) + +typedef struct _virNetDevMcastEntry virNetDevMcastEntry; +typedef virNetDevMcastEntry *virNetDevMcastEntryPtr; +struct _virNetDevMcastEntry { +int index; +char name[VIR_MCAST_NAME_LEN]; +int users; +bool global; +virMacAddr macaddr; +}; + +typedef struct _virNetDevMcast virNetDevMcast; +typedef virNetDevMcast *virNetDevMcastPtr; +struct _virNetDevMcast { +size_t
Re: [libvirt] [PATCH 1/2] util: Functions to update host network device's multicast filter
On 10/08/2014 12:59 PM, Eric Blake wrote: On 10/08/2014 09:36 AM, Laine Stump wrote: On 10/06/2014 05:37 PM, akrow...@linux.vnet.ibm.com wrote: From: Tony Krowiak This patch provides the utility functions to needed to synchronize the changes made to a guest domain network device's multicast filter with the corresponding macvtap device's filter on the host: * Get/add/remove multicast MAC addresses * Get the macvtap device's RX filter list Signed-off-by: Tony Krowiak --- +/** + * virMacAddrParseHex: + * @str: string hexadecimal representation of MAC address, e.g., "F801EFCE3aCB" + * @addr: 6-byte MAC address + * + * Parse the hexadecimal representation of a MAC address + * + * Return 0 upon success, or -1 in case of error. + */ +int +virMacAddrParseHex(const char* str, virMacAddrPtr addr) Wrong spacing around '*'. I will fix that. +{ +if (strlen(str) != VIR_MAC_HEXLEN) +return -1; + +size_t iaddr; +size_t istr; + + +for (istr = 0, iaddr = 0; iaddr < VIR_MAC_BUFLEN; istr += 2, iaddr++) { +unsigned int hex; + +if (sscanf(&str[istr], "%02x", &hex) != 1) +break; I'm not keen on sscanf(), but since we're already using it elsewhere, and the existing virMacAddrParse uses the normally-blacklisted strtoul() (and using virStrToLong_ui() on pieces of the string would require a terminating character after each piece), I don't have a ready answer for an alternative. Why not just open-code it? It's just two input bytes per iteration, and we already have a helper function that makes it a very short function. And strspn makes it easy to do input validation before starting the loop: int virMacAddrParseHex(const char *str, virMacAddrPtr addr) { size_t i; if (strspn(str, "0123456789abcdefABCDEF") != VIR_MAC_HEXLEN || str[VIR_MAC_HEXLEN]) return -1; for (i = 0; i < VIR_MAC_BUFLEN; i++) addr->addr[i] = (virHexToBin(str[2 * i]) << 4 | virHexToBin(str[2 * i + 1])); return 0; } Looks good, I'll put that in. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 1/3] docs, conf, schema: add support for shmem device
On 08.10.2014 18:57, Maxime Leroy wrote: Hi Martin, On Fri, Oct 3, 2014 at 10:45 PM, Martin Kletzander wrote: On Thu, Oct 02, 2014 at 09:42:36AM +0200, Michal Privoznik wrote: On 26.09.2014 12:43, Martin Kletzander wrote: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b114737..51bdd31 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c [..] Nice catch. Since we are past the release anyway, I'm going to push this in a while and whoever wants (e.g. Maxime) have the whole release cycle to test this. Thanks for pushing/cleaning the shmem patches support (i.e http://www.redhat.com/archives/libvir-list/2014-August/msg01032.html) But you did miss the following: 1. the ivshmem server autostart feature: you wanted me to develop it into the v1. (i.e. http://www.redhat.com/archives/libvir-list/2014-August/msg01432.html) 2. You did not wait for my tests. Why should I ask you to wait for my tests? Lucky enough, now I have the results of the tests, everything works fine ;) I don't understand why it became so urgent to push these patches. Well, I'm not intending to speak on Martin's behalf, but my workflow is as follows: when developing a new code I create a local branch and put the commits there. And as the development goes on, I keep the branch rebased onto the current master. However, depending on the complexity of the code, rebase conflicts are likely to occur - and that's rather unpleasant. So once the patches are ready I'm pushing them nearly ASAP for two reasons: to get rid of the rebasing (others may be working in the same area in near future too, so I'd spare them having rebase conflicts), and to test the feature. As soon as an pubclic API is not released, there's still an possibility to revert the patches if they turn out to be rubbish. So I'd say you both (you and Martin) obeyed the process. You've tested an upstream code. If it turned out that there's something wrong we could just fix it. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/2] util: Functions to update host network device's multicast filter
On 10/08/2014 09:36 AM, Laine Stump wrote: > On 10/06/2014 05:37 PM, akrow...@linux.vnet.ibm.com wrote: >> From: Tony Krowiak >> >> This patch provides the utility functions to needed to synchronize the >> changes made to a guest domain network device's multicast filter >> with the corresponding macvtap device's filter on the host: >> >> * Get/add/remove multicast MAC addresses >> * Get the macvtap device's RX filter list >> >> Signed-off-by: Tony Krowiak >> --- >> +/** >> + * virMacAddrParseHex: >> + * @str: string hexadecimal representation of MAC address, e.g., >> "F801EFCE3aCB" >> + * @addr: 6-byte MAC address >> + * >> + * Parse the hexadecimal representation of a MAC address >> + * >> + * Return 0 upon success, or -1 in case of error. >> + */ >> +int >> +virMacAddrParseHex(const char* str, virMacAddrPtr addr) Wrong spacing around '*'. >> +{ >> +if (strlen(str) != VIR_MAC_HEXLEN) >> +return -1; >> + >> +size_t iaddr; >> +size_t istr; >> + >> + >> +for (istr = 0, iaddr = 0; iaddr < VIR_MAC_BUFLEN; istr += 2, iaddr++) { >> +unsigned int hex; >> + >> +if (sscanf(&str[istr], "%02x", &hex) != 1) >> +break; > > I'm not keen on sscanf(), but since we're already using it elsewhere, > and the existing virMacAddrParse uses the normally-blacklisted strtoul() > (and using virStrToLong_ui() on pieces of the string would require a > terminating character after each piece), I don't have a ready answer for > an alternative. Why not just open-code it? It's just two input bytes per iteration, and we already have a helper function that makes it a very short function. And strspn makes it easy to do input validation before starting the loop: int virMacAddrParseHex(const char *str, virMacAddrPtr addr) { size_t i; if (strspn(str, "0123456789abcdefABCDEF") != VIR_MAC_HEXLEN || str[VIR_MAC_HEXLEN]) return -1; for (i = 0; i < VIR_MAC_BUFLEN; i++) addr->addr[i] = (virHexToBin(str[2 * i]) << 4 | virHexToBin(str[2 * i + 1])); return 0; } -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 1/3] docs, conf, schema: add support for shmem device
Hi Martin, On Fri, Oct 3, 2014 at 10:45 PM, Martin Kletzander wrote: > On Thu, Oct 02, 2014 at 09:42:36AM +0200, Michal Privoznik wrote: >> >> On 26.09.2014 12:43, Martin Kletzander wrote: >>> >>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c >>> index b114737..51bdd31 100644 >>> --- a/src/conf/domain_conf.c >>> +++ b/src/conf/domain_conf.c >> >> [..] >> > > Nice catch. > > Since we are past the release anyway, I'm going to push this in a > while and whoever wants (e.g. Maxime) have the whole release cycle to > test this. > Thanks for pushing/cleaning the shmem patches support (i.e http://www.redhat.com/archives/libvir-list/2014-August/msg01032.html) But you did miss the following: 1. the ivshmem server autostart feature: you wanted me to develop it into the v1. (i.e. http://www.redhat.com/archives/libvir-list/2014-August/msg01432.html) 2. You did not wait for my tests. Why should I ask you to wait for my tests? Lucky enough, now I have the results of the tests, everything works fine ;) I don't understand why it became so urgent to push these patches. Anyway, I am glad that libvirt supports ivshmem. Since now you pushed these patches, do you plan to provide the ivshmem autostart feature like you requested previously ? I'll be glad to review it and to provide feedbacks based on my tests. Maxime -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] security_selinux: Don't relabel /dev/net/tun
On 10/08/2014 07:23 AM, Michal Privoznik wrote: >>> +if (!STRPREFIX(fd_path, "/dev/tap")) { >> >> Should this be "/dev/tap.", since... >> >>> +VIR_DEBUG("fd=%d points to %s not setting SELinux label", >>> + fd, fd_path); >>> +rc = 0; >>> +goto cleanup; >>> +} >>> + >>> if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) { >> >> ...you require a '.' in the context lookup? Without the '.' in the >> filter, you would let the (unlikely) name '/dev/tapX' get through. >> >> ACK with that tweaked. >> >> > > In fact, /dev/tapX is what is created. getContext should be using it too > as it accepts shell expendable names, not regular expressions. I'm > adjusting getContext's argument too. I assume "shell expendable" meant "glob" :) Oh wow - so you're saying the only reason this even worked is that getContext was getting lucky and realizing that any file that matches the stricter glob '/dev/tap.*' also matches the looser glob '/dev/tap*', and that we were lucky the context rule we were trying to look up was not written against a tighter glob such as '/dev/tap[0-9]*'. Yes, you've convinced me that the name really is /dev/tapX and that removing the spurious '.' in the call to getContext is correct. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 1/21] hyperv: avoid query memleaks on failure
The function hypervEnumAndPull consumes query on success, but leaked it on failure. Rather than having to change all callers (many of them indirect callers through the generated hypervGetMsvmComputerSystemList), it was easier to just guarantee that the buffer is cleaned on return from the function. Reported by Yves Vinter. * src/hyperv/hyperv_wmi.c (hypervEnumAndPull): Don't leak query on failure. Signed-off-by: Eric Blake --- src/hyperv/hyperv_wmi.c | 37 + 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index acb705c..3027601 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -2,6 +2,7 @@ * hyperv_wmi.c: general WMI over WSMAN related functions and structures for * managing Microsoft Hyper-V hosts * + * Copyright (C) 2014 Red Hat, Inc. * Copyright (C) 2011 Matthias Bolte * Copyright (C) 2009 Michael Sievers * @@ -105,6 +106,7 @@ hyperyVerifyResponse(WsManClient *client, WsXmlDocH response, * Object */ +/* This function guarantees that query is freed, even on failure */ int hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root, XmlSerializerInfo *serializerInfo, const char *resourceUri, @@ -123,25 +125,28 @@ hypervEnumAndPull(hypervPrivate *priv, virBufferPtr query, const char *root, XML_TYPE_PTR data = NULL; hypervObject *object; -if (list == NULL || *list != NULL) { -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); +if (virBufferCheckError(query) < 0) { +virBufferFreeAndReset(query); return -1; } - -if (virBufferCheckError(query) < 0) -return -1; - -serializerContext = wsmc_get_serialization_context(priv->client); - -options = wsmc_options_init(); - -if (options == NULL) { -virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Could not initialize options")); -goto cleanup; -} - query_string = virBufferContentAndReset(query); + +if (list == NULL || *list != NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); +VIR_FREE(query_string); +return -1; +} + +serializerContext = wsmc_get_serialization_context(priv->client); + +options = wsmc_options_init(); + +if (options == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize options")); +goto cleanup; +} + filter = filter_create_simple(WSM_WQL_FILTER_DIALECT, query_string); if (filter == NULL) { -- 1.9.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 01/21] Added missing virBufferFreeAndReset on the query buffer to free some memory
On 10/08/2014 06:33 AM, Yves Vinter wrote: > From: yvinter Your git config is incorrect; your email headers list your full name 'Yves Vinter' but this line means that git is trying to attribute to the authorship to your username 'yvinter'. We prefer that the git history include a full legal name rather than a username abbreviation. Long subject line; the first line of a commit message should generally be no more than about 60 characters, so that 'git log --oneline -30' still fits the information comfortably in an 80-column screen. Also, it is nice to include a 'topic:' lead-in. Ideally, the one-line summary is the "what", and then the rest of the commit message after a blank line is the "why". So I suggest: hyperv: avoid memory leaks Add missing virBufferFreeAndReset on query buffers used throughout the hyperv code. as well as mention any valgrind testing you did to prove that the leaks are fixed. > +++ b/src/hyperv/hyperv_driver.c > @@ -201,6 +201,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr > auth, unsigned int flags > VIR_FREE(username); > VIR_FREE(password); > hypervFreeObject(priv, (hypervObject *)computerSystem); > +virBufferFreeAndReset(&query); Hmmm. query is initialized empty, until it is used in this code a few lines earlier: virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); virBufferAddLit(&query, "where "); virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL); if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) { goto cleanup; but tracing through that code, hypervGetMsvmComputerSystemList in hyperv_wmi.generated.c calls hypervEnumAndPull in hyperv_wmi.c, which in turn calls virBufferContentAndReset(query) on the success path, leaving nothing to clean up here. Okay, I see where hypervEnumAndPull can return early without cleaning query; I wonder if it would have been better to patch THAT function to guarantee that the buffer is always clean on return, rather than having to patch every single caller. In fact, after looking through the entire patch, it looks like EVERY single addition of virBufferFreeAndReset(&query) is only ever useful in any case where hypervEnumAndPull returns early. I'm going to reply to this mail with an alternative shorter patch. I don't have access to hyperv to test it under an actual valgrind run, but it compiled for me. Can you please run it through your test setup to see if it solves the issues you were initially trying to address? -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] hotplug: Fix libvirtd crash on qemu-attached guest
On 25.09.2014 17:00, John Ferlan wrote: https://bugzilla.redhat.com/show_bug.cgi?id=1141621 The crash in this case was because the qemu-attach code did not create aliases for qemu cli args. When the detach-interface code was called it assumed aliases were set resulting in a core when dereferencing the still NULL alias. Adding a call to qemuAssignDeviceAliases() resolves the path for qemu-attach; however, to prevent future issues an additional check for a NULL value is made and an error provided in the deatch path. Add some more verbiage to the virsh man page. Signed-off-by: John Ferlan --- v1 is here: http://www.redhat.com/archives/libvir-list/2014-September/msg01331.html Changes since v1: - Add the call to qemuAssignDeviceAliases() in qemuDomainQemuAttach(). - Move the check for NULL alias inside the CAPS_DEVICE check and emit an error rather than trying to remove as an "else" condition. src/qemu/qemu_driver.c | 3 +++ src/qemu/qemu_hotplug.c | 7 +++ tools/virsh.pod | 5 +++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 117138a..ef4ecd2 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14746,6 +14746,9 @@ static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn, if (qemuCanonicalizeMachine(def, qemuCaps) < 0) goto cleanup; +if (qemuAssignDeviceAliases(def, qemuCaps) < 0) +goto cleanup; + if (qemuDomainAssignAddresses(def, qemuCaps, NULL) < 0) goto cleanup; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index d631887..daebe82 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3521,6 +3521,13 @@ qemuDomainDetachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitor(driver, vm); if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { +if (!detach->info.alias) { +virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("device alias not found: cannot delete the " + "net device")); +qemuDomainObjExitMonitor(driver, vm); +goto cleanup; +} Is there a reason to not check this upfront rather than this late in the process? And I don't think that net devices are the only thing affected here. For instance a virtio disks seems vulnerable too (well, at first glance on the code). if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { The other possibility would be to make qemuMonitorDelDevice fail on @devalias == NULL. qemuDomainObjExitMonitor(driver, vm); virDomainAuditNet(vm, detach, NULL, "detach", false); diff --git a/tools/virsh.pod b/tools/virsh.pod index eae9195..bd17f68 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -3698,8 +3698,9 @@ using the UNIX driver. Ideally the process will also have had the Not all functions of libvirt are expected to work reliably after attaching to an externally launched QEMU process. There may be -issues with the guest ABI changing upon migration, and hotunplug -may not work. +issues with the guest ABI changing upon migration and device hotplug +or hotunplug may not work. The attached environment should be considered +primarily read-only. =item B I { [I<--hmp>] | [I<--pretty>] } I... Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCHv2] Introduce virStringStripIPv6Brackets
On 10/08/2014 04:31 AM, Ján Tomko wrote: > Helper function to strip the brackets from an IPv6 address. > Tested by viruritest. > --- > src/libvirt_private.syms | 1 + > src/util/virstring.c | 22 ++ > src/util/virstring.h | 2 ++ > src/util/viruri.c| 20 > tests/virstringtest.c| 49 > > 5 files changed, 78 insertions(+), 16 deletions(-) > > return virBufferContentAndReset(&buf); > } > + > +/** Two blank lines between functions seems to be the prevailing style. > +len = strlen(str); > +if (str[0] == '[' && str[len-1] == ']' && strchr(str, ':')) { Spaces around '-' ACK with those tweaks -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/2] util: Functions to update host network device's multicast filter
On 10/06/2014 05:37 PM, akrow...@linux.vnet.ibm.com wrote: > From: Tony Krowiak > > This patch provides the utility functions to needed to synchronize the > changes made to a guest domain network device's multicast filter > with the corresponding macvtap device's filter on the host: > > * Get/add/remove multicast MAC addresses > * Get the macvtap device's RX filter list > > Signed-off-by: Tony Krowiak > --- > src/libvirt_private.syms |4 + > src/util/virmacaddr.c| 37 + > src/util/virmacaddr.h|4 + > src/util/virnetdev.c | 360 > ++ > src/util/virnetdev.h | 11 ++ > 5 files changed, 416 insertions(+), 0 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index d6265ac..6d06a2c 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1590,13 +1590,16 @@ virMacAddrIsBroadcastRaw; > virMacAddrIsMulticast; > virMacAddrIsUnicast; > virMacAddrParse; > +virMacAddrParseHex; > virMacAddrSet; > virMacAddrSetRaw; > > > # util/virnetdev.h > +virNetDevAddMulti; > virNetDevAddRoute; > virNetDevClearIPv4Address; > +virNetDevDelMulti; > virNetDevExists; > virNetDevGetIndex; > virNetDevGetIPv4Address; > @@ -1604,6 +1607,7 @@ virNetDevGetLinkInfo; > virNetDevGetMAC; > virNetDevGetMTU; > virNetDevGetPhysicalFunction; > +virNetDevGetRxFilter; > virNetDevGetVirtualFunctionIndex; > virNetDevGetVirtualFunctionInfo; > virNetDevGetVirtualFunctions; > diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c > index ebd1182..ae5e5d2 100644 > --- a/src/util/virmacaddr.c > +++ b/src/util/virmacaddr.c > @@ -198,6 +198,43 @@ virMacAddrFormat(const virMacAddr *addr, > return str; > } > > +/** > + * virMacAddrParseHex: > + * @str: string hexadecimal representation of MAC address, e.g., > "F801EFCE3aCB" > + * @addr: 6-byte MAC address > + * > + * Parse the hexadecimal representation of a MAC address > + * > + * Return 0 upon success, or -1 in case of error. > + */ > +int > +virMacAddrParseHex(const char* str, virMacAddrPtr addr) > +{ > +if (strlen(str) != VIR_MAC_HEXLEN) > +return -1; > + > +size_t iaddr; > +size_t istr; > + > + > +for (istr = 0, iaddr = 0; iaddr < VIR_MAC_BUFLEN; istr += 2, iaddr++) { > +unsigned int hex; > + > +if (sscanf(&str[istr], "%02x", &hex) != 1) > +break; I'm not keen on sscanf(), but since we're already using it elsewhere, and the existing virMacAddrParse uses the normally-blacklisted strtoul() (and using virStrToLong_ui() on pieces of the string would require a terminating character after each piece), I don't have a ready answer for an alternative. Eric, do you have an opinion on this? Is sscanf okay when we want to parse: of hex digits into 6 binary bytes? > + > +if (hex > UCHAR_MAX) > +break; > + > +addr->addr[iaddr] = hex; > +} > + > +if (istr == VIR_MAC_HEXLEN) > +return 0; > + > +return -1; > +} > + > void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN], > virMacAddrPtr addr) > { > diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h > index 49efc36..72a285a 100644 > --- a/src/util/virmacaddr.h > +++ b/src/util/virmacaddr.h > @@ -27,6 +27,7 @@ > # include "internal.h" > > # define VIR_MAC_BUFLEN 6 > +#define VIR_MAC_HEXLEN (VIR_MAC_BUFLEN * 2) > # define VIR_MAC_PREFIX_BUFLEN 3 > # define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) > > @@ -50,6 +51,9 @@ void virMacAddrGenerate(const unsigned char > prefix[VIR_MAC_PREFIX_BUFLEN], > virMacAddrPtr addr); > int virMacAddrParse(const char* str, > virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK; > +int virMacAddrParseHex(const char* str, > + virMacAddrPtr addr) > +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; > bool virMacAddrIsUnicast(const virMacAddr *addr); > bool virMacAddrIsMulticast(const virMacAddr *addr); > bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]); > diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c > index db5623a..5e53f5f 100644 > --- a/src/util/virnetdev.c > +++ b/src/util/virnetdev.c > @@ -56,6 +56,33 @@ > > VIR_LOG_INIT("util.netdev"); > > +# define VIR_MCAST_NAME_LEN (IFNAMSIZ + 1) > +# define VIR_MCAST_INDEX_TOKEN_IDX 0 > +# define VIR_MCAST_NAME_TOKEN_IDX 1 > +# define VIR_MCAST_USERS_TOKEN_IDX 2 > +# define VIR_MCAST_GLOBAL_TOKEN_IDX 3 > +# define VIR_MCAST_ADDR_TOKEN_IDX 4 > +# define VIR_MCAST_NUM_TOKENS 5 > +# define VIR_MCAST_TOKEN_DELIMS " \n" > +# define VIR_MCAST_ADDR_LEN (VIR_MAC_HEXLEN + 1) > + > +typedef struct _virNetDevMcastEntry virNetDevMcastEntry; > +typedef virNetDevMcastEntry *virNetDevMcastEntryPtr; > +struct _virNetDevMcastEntry { > +int index; > +char name[VIR_MCAST_NAME_LEN]; > +int users; > +bool global; > +v
Re: [libvirt] Implementation of new features for Hyper-V Libvirt driver
[the original message got eaten by the moderator queue because of size violation] On 12/31/1969 05:00 PM, wrote: > Hi all, > > I've just submitted a set of 21 patchs for the implementation of new features > in the hyperv libvirt driver. > For your convenience, I have attached to this email a document giving more > details about this delivery. Rather than sending a 450k pdf describing the changes, just submit the changes themselves, one email per change. 'git send-email origin --cover-letter --annotate' can work miracles at giving you a chance to write a 0/21 cover letter that summarizes the rest of the series, and then 21 emails at one per patch. Doing it in this manner will make it much more likely that your series gets a timely review. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 6/8] Implemented post-copy migration logic in qemu
On 07 Oct 2014, at 23:02 , Jiri Denemark wrote: > On Tue, Sep 30, 2014 at 16:39:27 +0200, Cristian Klein wrote: >> Perform phase stops once migration switched to post-copy. >> Confirm phase waits for post-copy to finish before killing the VM. >> >> Signed-off-by: Cristian Klein >> --- >> src/qemu/qemu_driver.c| 8 >> src/qemu/qemu_migration.c | 25 ++--- >> 2 files changed, 30 insertions(+), 3 deletions(-) >> >> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c >> index e873d45..3fe2216 100644 >> --- a/src/qemu/qemu_driver.c >> +++ b/src/qemu/qemu_driver.c >> @@ -10942,6 +10942,14 @@ qemuDomainMigratePrepare2(virConnectPtr dconn, >> >> virCheckFlags(QEMU_MIGRATION_FLAGS, -1); >> >> +if (flags & VIR_MIGRATE_POSTCOPY) { >> +/* post-copy migration does not work with Sequence v2 */ >> +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", >> + _("Post-copy migration requested but not " >> + "supported by v2 protocol")); >> +goto cleanup; >> +} >> + > > This code should be unreachable. If both source and destination daemons > support VIR_MIGRATE_POSTCOPY, they support v3 protocol as well. And a > client new enough to specify VIR_MIGRATE_POSTCOPY will also support v3 > migration protocol. However, it doesn't hurt to check this to be safe. > >> if (flags & VIR_MIGRATE_TUNNELLED) { >> /* this is a logical error; we never should have gotten here with >> * VIR_MIGRATE_TUNNELLED set >> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c >> index 4a36946..436b701 100644 >> --- a/src/qemu/qemu_migration.c >> +++ b/src/qemu/qemu_migration.c >> @@ -2039,6 +2039,11 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver, >> ret = 0; >> break; >> >> +case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY_ACTIVE: >> +jobInfo->type = VIR_DOMAIN_JOB_PHASE1_COMPLETED; >> +ret = 0; >> +break; >> + > > This will need to be dropped after 5/8 is removed. However, it reminds > me... > >enum { >QEMU_MONITOR_MIGRATION_STATUS_INACTIVE, >QEMU_MONITOR_MIGRATION_STATUS_ACTIVE, >QEMU_MONITOR_MIGRATION_STATUS_COMPLETED, >QEMU_MONITOR_MIGRATION_STATUS_ERROR, >QEMU_MONITOR_MIGRATION_STATUS_CANCELLED, >QEMU_MONITOR_MIGRATION_STATUS_SETUP, >QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY_ACTIVE, > >QEMU_MONITOR_MIGRATION_STATUS_LAST >}; > > in qemu_monitor.h needs to be turned into a proper typedef so that > >switch (status.status) { > > line in qemuMigrationUpdateJobStatus may be changed to explicitly > mention the enum so that the compiler may report a warning whenever we > add new status but forgot to handle it in this switch. What about `QEMU_MONITOR_MIGRATION_STATUS_LAST`? Should this be included in a switch with an assertion that that code should never be reached? > Which means the > new state will need to be handled in the same patch it was introduced, > i.e, in 3/8. > >> case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: >> jobInfo->type = VIR_DOMAIN_JOB_NONE; >> virReportError(VIR_ERR_OPERATION_FAILED, >> @@ -2077,6 +2082,7 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, >> qemuDomainJobInfoPtr jobInfo = priv->job.current; >> const char *job; >> int pauseReason; >> +bool inPhase2 = (jobInfo->type == VIR_DOMAIN_JOB_PHASE1_COMPLETED); > > I think it would be cleaner to pass this info in a new parameter for > qemuMigrationWaitForCompletion instead of doing a hidden black magic > here. I agree with you, I wasn’t sure about with this way of coding things either. Is it okey to ask developers to always create a new intermediate parameter to call this function, so as to make its usage easier to read? E.g., “”” bool return_on_postcopy_active = false; rv = qemuMigrationWaitForCompletion(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, conn, abort_on_error, return_on_postcopy_active); “”" > >> >> switch (priv->job.asyncJob) { >> case QEMU_ASYNC_JOB_MIGRATION_OUT: >> @@ -2092,9 +2098,11 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr >> driver, >> job = _("job"); >> } >> >> -jobInfo->type = VIR_DOMAIN_JOB_UNBOUNDED; >> +if (!inPhase2) >> +jobInfo->type = VIR_DOMAIN_JOB_UNBOUNDED; >> >> -while (jobInfo->type == VIR_DOMAIN_JOB_UNBOUNDED) { >> +while (jobInfo->type == VIR_DOMAIN_JOB_UNBOUNDED || >> + (inPhase2 && jobInfo->type == VIR_DOMAIN_JOB_PHASE1_COMPLETED)) { > > Just use jobInfo->status.status directly. > >> /* Poll every 50ms for progress & to allow cancellation */ >> struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull }; >> >> @@ -2123,7 +2131,8 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, >>
Re: [libvirt] [PATCH v2 5/8] Added job type VIR_DOMAIN_JOB_PHASE1_COMPLETED
On 07 Oct 2014, at 22:08 , Jiri Denemark wrote: > On Tue, Sep 30, 2014 at 16:39:26 +0200, Cristian Klein wrote: >> Some jobs feature several phases. For example, post-copy migration is >> composed of a first phase, from migration start to switching to >> post-copy, and a second phase, to migration completion. This >> job type allows to flag that the job has completed the first phase, >> but is not yet fully completed. >> >> Signed-off-by: Cristian Klein >> --- >> include/libvirt/libvirt.h.in | 1 + >> tools/virsh-domain.c | 3 ++- >> 2 files changed, 3 insertions(+), 1 deletion(-) >> >> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in >> index 84cd5a4..81044f0 100644 >> --- a/include/libvirt/libvirt.h.in >> +++ b/include/libvirt/libvirt.h.in >> @@ -4307,6 +4307,7 @@ typedef enum { >> VIR_DOMAIN_JOB_COMPLETED = 3, /* Job has finished, but isn't cleaned up >> */ >> VIR_DOMAIN_JOB_FAILED= 4, /* Job hit error, but isn't cleaned up */ >> VIR_DOMAIN_JOB_CANCELLED = 5, /* Job was aborted, but isn't cleaned up */ >> +VIR_DOMAIN_JOB_PHASE1_COMPLETED = 6, /* Job completed first phase, >> e.g., post-copy activation */ > > This is not a job type. If we need to advertise this to libvirt clients, > we may introduce a new job statistics typed parameter but we should not > misuse job type. And I'm not entirely convinced we need to advertise > this. To me it seems the only interested thing is whether a domain is > still running on the source host or it was already resumed on the > destination host. And it's easy to get this kind of information via > existing ways, e.g., listening to domain life cycle events or by > checking domain's status. My rationale for introducing this flag was to prevent a future breakage of an internal API. I felt like none of the previous flags where accurately representing the status of this job after post-copy has started. Sure, I could use `job->status.status` in `qemuMigrationWaitForCompletion`, but I was concerned that a future `libvirt` addition might not take this subtly into account and might break post-copy. If you think I should go ahead, suppress this job type and use `job->status.status` instead, what should I use instead, `VIR_DOMAIN_JOB_UNBOUNDED` or `VIR_DOMAIN_JOB_BOUNDED`? To be honest, I’m not sure to have completely understood the difference between them, except that `VIR_DOMAIN_JOB_BOUNDED` seems to be used to signal that a job is almost complete. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 18/21] Added hypervDomainAttachDisk, internal implementation for disk attachement (required Msvm_ResourceAllocationSettingData and Msvm_AllocationCapabilities classes)
From: yvinter --- src/hyperv/hyperv_driver.c| 377 ++ src/hyperv/hyperv_wmi_generator.input | 41 2 files changed, 418 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f68eaad..cbe4397 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2424,6 +2424,383 @@ hypervDomainUndefine(virDomainPtr domain) +/* + * Creates the attribute __PATH for the RASD object + * The attribute is build like this: + * \\\root\virtualization:Msvm_ResourceAllocationSettingData.InstanceID="" + * where backslashes in rasdInstanceID are doubled + */ +static int +hypervGetResourceAllocationSettingDataPATH(virDomainPtr domain, char *rasdInstanceID, char **__path) +{ +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_ComputerSystem *computerSystem = NULL; +char *strTemp = NULL; +int result = -1, i = 0, j = 0, n = 0; + +virUUIDFormat(domain->uuid, uuid_string); + +/* Get host name */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_HostedDependency " + "ResultClass = Msvm_ComputerSystem", + uuid_string); +if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) { +goto cleanup; +} +if (computerSystem == NULL) { +virReportError(VIR_ERR_NO_DOMAIN, _("No domain with UUID %s"), uuid_string); +goto cleanup; +} + +/* Count the number of backslash character */ +strTemp = strchr(rasdInstanceID, '\\'); +while (strTemp != NULL) { +n++; +strTemp = strchr(++strTemp, '\\'); +} +/* Double the blackslashes */ +if (VIR_ALLOC_N(strTemp, strlen(rasdInstanceID) + 1 + n) < 0) +goto cleanup; +while (rasdInstanceID[i] != '\0') { +strTemp[j] = rasdInstanceID[i]; +if (rasdInstanceID[i] == '\\') { +j++; +strTemp[j] = '\\'; +} +i++; +j++; +} +strTemp[j] = '\0'; + +/* Create the attribute __PATH */ +/* FIXME: *__path allocated with 255 characters (static value) */ +if (VIR_ALLOC_N(*__path, 255) < 0) +goto cleanup; +sprintf(*__path, ""); +strcat(*__path, computerSystem->data->ElementName); +strcat(*__path, "\\root\\virtualization:Msvm_ResourceAllocationSettingData.InstanceID=\""); +strcat(*__path, strTemp); +strcat(*__path, "\""); + +result = 0; + + cleanup: +VIR_FREE(strTemp); +hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); + +return result; +} + + + +/* hypervDomainAttachDisk + * FIXME: + * - added ressources must me removed in case of error + * - allow attaching disks on iSCSI (implemented only on IDE) + * - allow attaching ISO images (on DVD devices) + * - implement associated detach method + */ +ATTRIBUTE_UNUSED static int +hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk) +{ +int result = -1, nb_params; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +char *ideRasdPath = NULL, *newDiskDrivePath = NULL; +char ideControler[2], ideControlerAddr[2]; +hypervPrivate *priv = domain->conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +Msvm_ResourceAllocationSettingData *resourceAllocationSettingData = NULL; +Msvm_ResourceAllocationSettingData *resourceAllocationSettingData2 = NULL; +Msvm_ResourceAllocationSettingData *resourceAllocationSettingData3 = NULL; +Msvm_ResourceAllocationSettingData *resourceAllocationSettingData4 = NULL; +Msvm_ResourceAllocationSettingData *ideRasd = NULL; /* resourceAllocationSettingData subtree -> do not disallocate */ +Msvm_ResourceAllocationSettingData *diskRasd = NULL; /* resourceAllocationSettingData2 subtree -> do not disallocate */ +Msvm_ResourceAllocationSettingData *newDiskDrive = NULL; /* resourceAllocationSettingData3 subtree -> do not disallocate */ +Msvm_AllocationCapabilities *allocationCapabilities = NULL; +Msvm_AllocationCapabilities *allocationCapabilities2 = NULL; +invokeXmlParam *params = NULL; +properties_t *tab_props = NULL; +eprParam eprparam1, eprparam2; +embeddedParam embeddedparam1, embeddedparam2; + +/* Initialization */ +virUUIDFormat(domain->uuid, uuid_string); + +/* Set IDE Controler 0 or 1 and address 0 or 1 */ +if (STREQ(disk->dst, "hda")) { +sprintf(ideControler, "%d", 0); +sprintf(ideControlerAddr, "%d", 0); +}
[libvirt] [PATCH 16/21] Added implementation for virDomainSetVcpus and virDomainSetVcpusFlags
From: yvinter --- src/hyperv/hyperv_driver.c | 118 + 1 file changed, 118 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index a8d679e..ade9db1 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2237,6 +2237,122 @@ hypervDomainSetMemory(virDomainPtr domain, unsigned long memory) +static int +hypervDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, + unsigned int flags ATTRIBUTE_UNUSED) +{ +int result = -1; +invokeXmlParam *params = NULL; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +properties_t *tab_props = NULL; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +Msvm_ProcessorSettingData *processorSettingData = NULL; +eprParam eprparam; +embeddedParam embeddedparam; +int nb_params; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; +char *nvcpus_str = NULL; + +/* Convert nvcpus as a string value */ +nvcpus_str = num2str(nvcpus); +if (nvcpus_str == NULL) +goto cleanup; + +virUUIDFormat(domain->uuid, uuid_string); + +VIR_DEBUG("nvcpus=%s, uuid=%s", nvcpus_str, uuid_string); + +/* Get Msvm_VirtualSystemSettingData */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); + +if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) +goto cleanup; + +/* Get Msvm_ProcessorSettingData */ +virBufferFreeAndReset(&query); +virBufferAsprintf(&query, + "associators of " + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " + "where AssocClass = Msvm_VirtualSystemSettingDataComponent " + "ResultClass = Msvm_ProcessorSettingData", + virtualSystemSettingData->data->InstanceID); + +if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) +goto cleanup; + +if (processorSettingData == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup Msvm_ProcessorSettingData for domain %s"), + virtualSystemSettingData->data->ElementName); +goto cleanup; +} + +/* Prepare EPR param */ +virBufferFreeAndReset(&query); +virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); +virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string); +eprparam.query = &query; +eprparam.wmiProviderURI = ROOT_VIRTUALIZATION; + +/* Prepare EMBEDDED param */ +embeddedparam.nbProps = 2; +if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) +goto cleanup; +(*tab_props).name = "VirtualQuantity"; +(*tab_props).val = nvcpus_str; +(*(tab_props+1)).name = "InstanceID"; +(*(tab_props+1)).val = processorSettingData->data->InstanceID; +embeddedparam.instanceName = "Msvm_ProcessorSettingData"; +embeddedparam.prop_t = tab_props; + +/* Create invokeXmlParam */ +nb_params = 2; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "ComputerSystem"; +(*params).type = EPR_PARAM; +(*params).param = &eprparam; +(*(params+1)).name = "ResourceSettingData"; +(*(params+1)).type = EMBEDDED_PARAM; +(*(params+1)).param = &embeddedparam; + +if (hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain vcpus")); +goto cleanup; +} + +result = 0; + + cleanup: +VIR_FREE(tab_props); +VIR_FREE(params); +VIR_FREE(nvcpus_str); +hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); +hypervFreeObject(priv, (hypervObject *)processorSettingData); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) +{ +return hypervDomainSetVcpusFlags(domain, nvcpus, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2289,6 +2405,8 @@ static virDriver hypervDriver = { .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */ .domainSetMemory = hypervDomainSetMemory, /* 1.2.10 */ .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10 */ +.domainSetVcpus =
[libvirt] [PATCH 21/21] Added implementation for virDomainDefineXML and virDomainCreateXML
From: yvinter --- src/hyperv/hyperv_driver.c | 142 + 1 file changed, 142 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 8e0d6b3..83fb605 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -3098,6 +3098,146 @@ hypervDomainAttachDevice(virDomainPtr domain, const char *xml) +static virDomainPtr +hypervDomainDefineXML(virConnectPtr conn, const char *xml) +{ +hypervPrivate *priv = conn->privateData; +virDomainDefPtr def = NULL; +virDomainPtr domain = NULL; +invokeXmlParam *params = NULL; +properties_t *tab_props = NULL; +embeddedParam embeddedparam; +int nb_params, i; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; +char uuid_string[VIR_UUID_STRING_BUFLEN]; + +/* Parse XML domain description */ +if ((def = virDomainDefParseString(xml, priv->caps, priv->xmlopt, + 1 << VIR_DOMAIN_VIRT_HYPERV, VIR_DOMAIN_XML_INACTIVE)) == NULL) { +goto cleanup; +} + +/* Create the domain if does not exist */ +if (def->uuid == NULL || (domain = hypervDomainLookupByUUID(conn, def->uuid)) == NULL) { +/* Prepare EMBEDDED param */ +/* Edit only VM name */ +/* FIXME: cannot edit VM UUID */ +embeddedparam.nbProps = 1; +if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) +goto cleanup; +(*tab_props).name = "ElementName"; +(*tab_props).val = def->name; +embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData"; +embeddedparam.prop_t = tab_props; + +/* Create invokeXmlParam */ +nb_params = 1; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "SystemSettingData"; +(*params).type = EMBEDDED_PARAM; +(*params).param = &embeddedparam; + +/* Create VM */ +if (hypervInvokeMethod(priv, params, nb_params, "DefineVirtualSystem", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not create new domain %s"), def->name); +goto cleanup; +} + +/* Get domain pointer */ +domain = hypervDomainLookupByName(conn, def->name); + +VIR_DEBUG("Domain created: name=%s, uuid=%s", + domain->name, virUUIDFormat(domain->uuid, uuid_string)); +} + +/* Set VM maximum memory */ +if (def->mem.max_balloon > 0) { +if (hypervDomainSetMaxMemory(domain, def->mem.max_balloon) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not set VM maximum memory")); +} +} + +/* Set VM memory */ +if (def->mem.cur_balloon > 0) { +if (hypervDomainSetMemory(domain, def->mem.cur_balloon) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not set VM memory")); +} +} + +/* Set VM vcpus */ +if (def->vcpus > 0) { +if (hypervDomainSetVcpus(domain, def->vcpus) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not set VM vCPUs")); +} +} + +/* Attach networks */ +for (i = 0; i < def->nnets; i++) { +if (hypervDomainAttachNetwork(domain, def->nets[i]) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not attach network")); +} +} + +/* Attach disks */ +for (i = 0; i < def->ndisks; i++) { +if (hypervDomainAttachDisk(domain, def->disks[i]) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not attach disk")); +} +} + + cleanup: +virDomainDefFree(def); +VIR_FREE(tab_props); +VIR_FREE(params); + +return domain; +} + + + +static virDomainPtr +hypervDomainCreateXML(virConnectPtr conn, const char *xmlDesc, unsigned int flags) +{ +virDomainPtr domain; + +virCheckFlags(VIR_DOMAIN_START_PAUSED | VIR_DOMAIN_START_AUTODESTROY, NULL); + +/* Create the new domain */ +domain = hypervDomainDefineXML(conn, xmlDesc); +if (domain == NULL) +return NULL; + +/* Start the domain */ +if (hypervInvokeMsvmComputerSystemRequestStateChange(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not start the domain %s"), domain->name); +return domain; +} + +/* If the VIR_DOMAIN_START_PAUSED flag is set, + the guest domain will be started, but its CPUs will remain paused */ +if (flags & VIR_DOMAIN_START_PAUSED) { +if (hypervDomainSuspend(domain) < 0) { +virReportError(VIR_
[libvirt] [PATCH 20/21] Added implementation for virDomainAttachDevice and virDomainAttachDeviceFlags (required xmlopt in private structure)
From: yvinter --- src/hyperv/hyperv_driver.c | 81 + src/hyperv/hyperv_private.h | 2 ++ 2 files changed, 83 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 8b8e612..8e0d6b3 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -62,6 +62,9 @@ hypervFreePrivate(hypervPrivate **priv) if ((*priv)->caps != NULL) virObjectUnref((*priv)->caps); +if ((*priv)->xmlopt != NULL) +virObjectUnref((*priv)->xmlopt); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } @@ -206,6 +209,9 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags goto cleanup; } +/* Init xmlopt to parse Domain XML */ +priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL); + conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; @@ -3019,6 +3025,79 @@ hypervDomainAttachNetwork(virDomainPtr domain, virDomainNetDefPtr net) +static int +hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml, + unsigned int flags ATTRIBUTE_UNUSED) +{ +int result = -1; +hypervPrivate *priv = domain->conn->privateData; +virDomainDefPtr def = NULL; +virDomainDeviceDefPtr dev = NULL; +char *xmlDomain = NULL; + +/* Get domain definition */ +if ((xmlDomain = hypervDomainGetXMLDesc(domain, 0)) == NULL) { +goto cleanup; +} +if ((def = virDomainDefParseString(xmlDomain, priv->caps, priv->xmlopt, + 1 << VIR_DOMAIN_VIRT_HYPERV, VIR_DOMAIN_XML_INACTIVE)) == NULL) { +goto cleanup; +} + +/* Get domain device definition */ +if ((dev = virDomainDeviceDefParse(xml, def, priv->caps, + priv->xmlopt, VIR_DOMAIN_XML_INACTIVE)) == NULL) { +goto cleanup; +} + +switch (dev->type) { +/* Device = disk */ +case VIR_DOMAIN_DEVICE_DISK: +if (hypervDomainAttachDisk(domain, dev->data.disk) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not attach disk")); +goto cleanup; +} +VIR_DEBUG("Disk attached"); +break; + +/* Device = network */ +case VIR_DOMAIN_DEVICE_NET: +if (hypervDomainAttachNetwork(domain, dev->data.net) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not attach network")); +goto cleanup; +} +VIR_DEBUG("Network attached"); +break; + +/* Unsupported device type */ +default: +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Device attachment of type %d is not implemented"), dev->type); +goto cleanup; +} + +result = 0; + + cleanup: +virDomainDefFree(def); +virDomainDeviceDefFree(dev); +VIR_FREE(xmlDomain); + +return result; +} + + + +static int +hypervDomainAttachDevice(virDomainPtr domain, const char *xml) +{ +return hypervDomainAttachDeviceFlags(domain, xml, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -3075,6 +3154,8 @@ static virDriver hypervDriver = { .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.10 */ .domainUndefine = hypervDomainUndefine, /* 1.2.10 */ .domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.10 */ +.domainAttachDevice = hypervDomainAttachDevice, /* 1.2.10 */ +.domainAttachDeviceFlags = hypervDomainAttachDeviceFlags, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h index d9aa0bd..2dfce6e 100644 --- a/src/hyperv/hyperv_private.h +++ b/src/hyperv/hyperv_private.h @@ -27,6 +27,7 @@ # include "virerror.h" # include "hyperv_util.h" # include "capabilities.h" +# include "domain_conf.h" # include "openwsman.h" typedef struct _hypervPrivate hypervPrivate; @@ -35,6 +36,7 @@ struct _hypervPrivate { hypervParsedUri *parsedUri; WsManClient *client; virCapsPtr caps; +virDomainXMLOptionPtr xmlopt; }; #endif /* __HYPERV_PRIVATE_H__ */ -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 15/21] Added implementation for virDomainSetMemory and virDomainSetMemoryFlags
From: yvinter --- src/hyperv/hyperv_driver.c | 112 + 1 file changed, 112 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 0618ce1..a8d679e 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2127,6 +2127,116 @@ hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) +static int +hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory, + unsigned int flags ATTRIBUTE_UNUSED) +{ +int result = -1, nb_params; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +invokeXmlParam *params = NULL; +properties_t *tab_props = NULL; +eprParam eprparam; +embeddedParam embeddedparam; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +Msvm_MemorySettingData *memorySettingData = NULL; +unsigned long memory_mb = memory / 1024; /* Memory converted in MB */ +char *memory_str = NULL; + +/* Memory value must be a multiple of 2 MB; round up it accordingly if necessary */ +if (memory_mb % 2) memory_mb++; + +/* Convert the memory value as a string */ +memory_str = num2str(memory_mb); +if (memory_str == NULL) +goto cleanup; + +virUUIDFormat(domain->uuid, uuid_string); + +VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string); + +/* Get Msvm_VirtualSystemSettingData */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); +if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) +goto cleanup; + +/* Get Msvm_MemorySettingData */ +virBufferFreeAndReset(&query); +virBufferAsprintf(&query, + "associators of " + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " + "where AssocClass = Msvm_VirtualSystemSettingDataComponent " + "ResultClass = Msvm_MemorySettingData", + virtualSystemSettingData->data->InstanceID); +if (hypervGetMsvmMemorySettingDataList(priv, &query, &memorySettingData) < 0) +goto cleanup; + +/* Prepare EPR param */ +virBufferFreeAndReset(&query); +virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); +virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string); +eprparam.query = &query; +eprparam.wmiProviderURI = ROOT_VIRTUALIZATION; + +/* Prepare EMBEDDED param */ +embeddedparam.nbProps = 2; +if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) +goto cleanup; +(*tab_props).name = "VirtualQuantity"; +(*tab_props).val = memory_str; +(*(tab_props+1)).name = "InstanceID"; +(*(tab_props+1)).val = memorySettingData->data->InstanceID; +embeddedparam.instanceName = "Msvm_MemorySettingData"; +embeddedparam.prop_t = tab_props; + +/* Create invokeXmlParam */ +nb_params = 2; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "ComputerSystem"; +(*params).type = EPR_PARAM; +(*params).param = &eprparam; +(*(params+1)).name = "ResourceSettingData"; +(*(params+1)).type = EMBEDDED_PARAM; +(*(params+1)).param = &embeddedparam; + +if (hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain memory")); +goto cleanup; +} + +result = 0; + + cleanup: +VIR_FREE(tab_props); +VIR_FREE(params); +VIR_FREE(memory_str); +hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); +hypervFreeObject(priv, (hypervObject *)memorySettingData); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervDomainSetMemory(virDomainPtr domain, unsigned long memory) +{ +return hypervDomainSetMemoryFlags(domain, memory, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2177,6 +2287,8 @@ static virDriver hypervDriver = { .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */ +.domainSetMemory = hypervDomainSetMemory, /* 1.2.10 */ +.domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10
[libvirt] [PATCH 19/21] Added hypervDomainAttachNetwork, internal implementation for network attachement (required Msvm_SwitchPort and Msvm_SyntheticEthernetPortSettingData classes)
From: yvinter --- src/hyperv/hyperv_driver.c| 218 ++ src/hyperv/hyperv_wmi_generator.input | 87 ++ 2 files changed, 305 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index cbe4397..8b8e612 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2801,6 +2801,224 @@ hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk) +/* + * Create the attribute __PATH for the SwitchPort object. + * The attribute is build like this: + * \\\root\virtualization:Msvm_SwitchPort.CreationClassName="Msvm_SwitchPort", + * Name="",SystemCreationClassName="Msvm_VirtualSwitch", + * SystemName="" + */ +static int +hypervGetSwitchPortPATH(virDomainPtr domain, char *switchPortName, char *virtualSwitchSystemName, char **__path) +{ +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_ComputerSystem *computerSystem = NULL; +int result = -1; + +virUUIDFormat(domain->uuid, uuid_string); + +/* Get host name */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_HostedDependency " + "ResultClass = Msvm_ComputerSystem", + uuid_string); +if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) { +goto cleanup; +} +if (computerSystem == NULL) { +virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with UUID %s"), uuid_string); +goto cleanup; +} + +/* Create the attribute __PATH */ +/* FIXME: *__path is allocated with 512 characters (static value) */ +if (VIR_ALLOC_N(*__path, 512) < 0) +goto cleanup; +sprintf(*__path, + "%s\\root\\virtualization:Msvm_SwitchPort.CreationClassName=\"Msvm_SwitchPort\"," + "Name=\"%s\",SystemCreationClassName=\"Msvm_VirtualSwitch\",SystemName=\"%s\"", +computerSystem->data->ElementName, switchPortName, virtualSwitchSystemName); + +result = 0; + + cleanup: +hypervFreeObject(priv, (hypervObject *) computerSystem); +virBufferFreeAndReset(&query); +return result; +} + + + +/* hypervDomainAttachNetwork + * FIXME: + * - implement associated detach method + */ +ATTRIBUTE_UNUSED static int +hypervDomainAttachNetwork(virDomainPtr domain, virDomainNetDefPtr net) +{ +int result = -1, nb_params; +const char *selector1 = "CreationClassName=Msvm_VirtualSwitchManagementService"; +const char *selector2 = "CreationClassName=Msvm_VirtualSystemManagementService"; +char uuid_string[VIR_UUID_STRING_BUFLEN], guid_string[VIR_UUID_STRING_BUFLEN]; +unsigned char guid[VIR_UUID_BUFLEN]; +char *virtualSystemIdentifiers = NULL, *switchPortPATH = NULL; +hypervPrivate *priv = domain->conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +eprParam eprparam1, eprparam2; +simpleParam simpleparam1, simpleparam2, simpleparam3; +embeddedParam embeddedparam; +properties_t *tab_props = NULL; +invokeXmlParam *params = NULL; +Msvm_SwitchPort *switchPort = NULL; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +/* Initialization */ +virUUIDFormat(domain->uuid, uuid_string); + +VIR_DEBUG("network=%s, uuid=%s", net->data.network.name, uuid_string); + +/* Create virtual switch port */ +/* Prepare EPR param 1 */ +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where ElementName = \"%s\"", net->data.network.name); +eprparam1.query = &query; +eprparam1.wmiProviderURI = ROOT_VIRTUALIZATION; + +/* Prepare SIMPLE params */ +virUUIDGenerate(guid); +virUUIDFormat(guid, guid_string); +simpleparam1.value = guid_string; +simpleparam2.value = "Dynamic Ethernet Switch Port"; +simpleparam3.value = ""; + +/* Create invokeXmlParam tab */ +nb_params = 4; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "VirtualSwitch"; +(*params).type = EPR_PARAM; +(*params).param = &eprparam1; +(*(params+1)).name = "Name"; +(*(params+1)).type = SIMPLE_PARAM; +(*(params+1)).param = &simpleparam1; +(*(params+2)).name = "FriendlyName"; +(*(params+2)).type = SIMPLE_PARAM; +(*(params+2)).param = &simpleparam2; +(*(params+3)).name = "ScopeOfResidence"; +(*(params+3)).type = SIMPLE_PARAM; +(*(params+3)).param = &simpleparam3; + +if (hypervInvokeMethod(priv, params, nb_params, "CreateSwitchPort", + MSVM_VIRTUALSWITCHMANAGEMENTSERVICE_RESOURCE_URI, selector1) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, +
[libvirt] [PATCH 14/21] Added implementation for virDomainSetMaxMemory
From: yvinter --- src/hyperv/hyperv_driver.c | 119 + 1 file changed, 119 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 5c79c99..0618ce1 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2009,6 +2009,124 @@ hypervDomainGetAutostart(virDomainPtr domain, int *autostart) +/* Format a number as a string value */ +static char *num2str(unsigned long value) +{ +int sz; +char *result; + +sz = snprintf (NULL, 0, "%lu", value); +if (VIR_ALLOC_N(result, sz + 1) < 0) { + return NULL; +} + +sprintf(result, "%lu", value); +return result; +} + + + +static int +hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) +{ +int result = -1; +invokeXmlParam *params = NULL; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +properties_t *tab_props = NULL; +virBuffer query = VIR_BUFFER_INITIALIZER; +virBuffer query2 = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +Msvm_MemorySettingData *memorySettingData = NULL; +eprParam eprparam; +embeddedParam embeddedparam; +int nb_params; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; +unsigned long memory_mb = memory/1024; +char *memory_str = NULL; + +/* Memory value must be a multiple of 2 MB; round up it accordingly if necessary */ +if (memory_mb % 2) memory_mb++; + +/* Convert the memory value as a string */ +memory_str = num2str(memory_mb); +if (memory_str == NULL) +goto cleanup; + +virUUIDFormat(domain->uuid, uuid_string); + +VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string); + +/* Prepare EPR param */ +virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); +virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string); +eprparam.query = &query; +eprparam.wmiProviderURI = ROOT_VIRTUALIZATION; + +/* Prepare EMBEDDED param 1 */ +/* Get Msvm_VirtualSystemSettingData */ +virBufferAsprintf(&query2, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); + +if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query2, &virtualSystemSettingData) < 0) +goto cleanup; + +/* Get Msvm_MemorySettingData */ +virBufferFreeAndReset(&query2); +virBufferAsprintf(&query2, + "associators of " + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " + "where AssocClass = Msvm_VirtualSystemSettingDataComponent " + "ResultClass = Msvm_MemorySettingData", + virtualSystemSettingData->data->InstanceID); + +if (hypervGetMsvmMemorySettingDataList(priv, &query2, &memorySettingData) < 0) +goto cleanup; + +embeddedparam.nbProps = 2; +if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) +goto cleanup; +(*tab_props).name = "Limit"; +(*tab_props).val = memory_str; +(*(tab_props+1)).name = "InstanceID"; +(*(tab_props+1)).val = memorySettingData->data->InstanceID; +embeddedparam.instanceName = "Msvm_MemorySettingData"; +embeddedparam.prop_t = tab_props; +embeddedparam.nbProps = 2; + +/* Create invokeXmlParam */ +nb_params = 2; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "ComputerSystem"; +(*params).type = EPR_PARAM; +(*params).param = &eprparam; +(*(params+1)).name = "ResourceSettingData"; +(*(params+1)).type = EMBEDDED_PARAM; +(*(params+1)).param = &embeddedparam; + +result = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector); + + cleanup: +VIR_FREE(tab_props); +VIR_FREE(params); +VIR_FREE(memory_str); +hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); +hypervFreeObject(priv, (hypervObject *)memorySettingData); +virBufferFreeAndReset(&query); +virBufferFreeAndReset(&query2); + +return result; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2058,6 +2176,7 @@ static virDriver hypervDriver = { .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.10 */ .domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ .domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ +.domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */ }; -- 1.9.1 -- libvir-list mailing
[libvirt] [PATCH 17/21] Added implementation for virDomainUndefine and virDomainUndefineFlags
From: yvinter --- src/hyperv/hyperv_driver.c | 73 ++ 1 file changed, 73 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index ade9db1..f68eaad 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -2353,6 +2353,77 @@ hypervDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) +static int +hypervDomainUndefineFlags(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED) +{ +int result = -1, nb_params; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +invokeXmlParam *params = NULL; +eprParam eprparam; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_ComputerSystem *computerSystem = NULL; + +virCheckFlags(0, -1); + +virUUIDFormat(domain->uuid, uuid_string); + +if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) { +goto cleanup; +} + +/* Shutdown the VM if not disabled */ +if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_DISABLED) { +if (hypervDomainShutdown(domain) < 0) { +goto cleanup; +} +} + +/* Deleting the VM */ + +/* Prepare EPR param */ +virBufferFreeAndReset(&query); +virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); +virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string); +eprparam.query = &query; +eprparam.wmiProviderURI = ROOT_VIRTUALIZATION; + +/* Create invokeXmlParam tab */ +nb_params = 1; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "ComputerSystem"; +(*params).type = EPR_PARAM; +(*params).param = &eprparam; + +/* Destroy VM */ +if (hypervInvokeMethod(priv, params, nb_params, "DestroyVirtualSystem", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not delete domain")); +goto cleanup; +} + +result = 0; + + cleanup: +VIR_FREE(params); +hypervFreeObject(priv, (hypervObject *) computerSystem); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervDomainUndefine(virDomainPtr domain) +{ +return hypervDomainUndefineFlags(domain, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -2407,6 +2478,8 @@ static virDriver hypervDriver = { .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10 */ .domainSetVcpus = hypervDomainSetVcpus, /* 1.2.10 */ .domainSetVcpusFlags = hypervDomainSetVcpusFlags, /* 1.2.10 */ +.domainUndefine = hypervDomainUndefine, /* 1.2.10 */ +.domainUndefineFlags = hypervDomainUndefineFlags, /* 1.2.10 */ }; -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 12/21] Added implementation of hypervInvokeMethod which handles complex parameters (simple, EPR or embedded)
From: yvinter --- src/hyperv/hyperv_wmi.c| 666 + src/hyperv/hyperv_wmi.h| 53 +++ src/hyperv/hyperv_wmi_generator.py | 59 src/hyperv/openwsman.h | 4 + 4 files changed, 782 insertions(+) diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index be84532..61fb540 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -22,6 +22,7 @@ */ #include +#include /* Where struct _WsXmlDoc is defined (necessary to dereference WsXmlDocH type) */ #include "internal.h" #include "virerror.h" @@ -32,6 +33,7 @@ #include "hyperv_private.h" #include "hyperv_wmi.h" #include "virstring.h" +#include "hyperv_wmi_cimtypes.generated.h" #define WS_SERIALIZER_FREE_MEM_WORKS 0 @@ -383,6 +385,670 @@ hypervReturnCodeToString(int returnCode) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * hypervInvokeMethod + * Function to invoke WSMAN request with simple, EPR or embedded parameters + */ + +/* Create XML structure */ +static int +hypervCreateXmlStruct(const char *methodName, const char *classURI, + WsXmlDocH *xmlDocRoot, WsXmlNodeH *xmlNodeMethod) +{ +virBuffer method_buff = VIR_BUFFER_INITIALIZER; +char *methodNameInput = NULL; + +virBufferAsprintf(&method_buff, "%s_INPUT", methodName); +methodNameInput = virBufferContentAndReset(&method_buff); + +if (methodNameInput == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Could not create Xml Doc")); +goto cleanup; +} + +*xmlDocRoot = ws_xml_create_doc(NULL, methodNameInput); +if (*xmlDocRoot == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Could not create Xml Doc with given parameter xmlDocRoot")); +goto cleanup; +} + +*xmlNodeMethod = xml_parser_get_root(*xmlDocRoot); +if (*xmlNodeMethod == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Could not get xmlDocRoot root node")); +goto cleanup; +} + +/* Add namespace to xmlNodeMethode */ +ws_xml_set_ns(*xmlNodeMethod, classURI, "p"); + +VIR_FREE(methodNameInput); +return 0; + + cleanup: + +virBufferFreeAndReset(&method_buff); +VIR_FREE(methodNameInput); +if (*xmlDocRoot != NULL) { +ws_xml_destroy_doc(*xmlDocRoot); +*xmlDocRoot = NULL; +} + +return -1; +} + + +/* Look for the type of a given property class and specifies if it is an array */ +static int +hypervGetPropType(const char *className, const char *propName, const char **propType, bool *isArray) +{ +int i, y; + +i = 0; +while (cimClasses[i].name[0] != '\0') { +if (STREQ(cimClasses[i].name, className)){ +y = 0; +while (cimClasses[i].cimTypesPtr[y].name[0] != '\0') { +if (STREQ(cimClasses[i].cimTypesPtr[y].name, propName)){ +*propType = cimClasses[i].cimTypesPtr[y].type; +*isArray = cimClasses[i].cimTypesPtr[y].isArray; +return 0; +} +y++; +} +break; +} +i++; +} + +return -1; +} + + +/* Adding an Simple param node to a parent node given in parameter */ +static int +hypervAddSimpleParam(const char *paramName, const char* value, + const char *classURI, WsXmlNodeH *parentNode) +{ +int result = -1; +WsXmlNodeH xmlNodeParam = NULL; + +xmlNodeParam = ws_xml_add_child(*parentNode, classURI, paramName, value); +if (xmlNodeParam == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not create simple param")); +goto cleanup; +} + +result = 0; + + cleanup: +return result; +} + + +/* Adding EPR param node to a parent node given in parameter */ +static int +hypervAddEprParam(const char *paramName, virBufferPtr query, const char *root, + const char *classURI, WsXmlNodeH *parentNode, WsXmlDocH doc, hypervPrivate *priv) +{ + +int result = -1; +WsXmlNodeH xmlNodeParam = NULL; +WsXmlNodeH xmlNodTemp = NULL; +WsXmlNodeH xmlNodeAdr = NULL; +WsXmlNodeH xmlNodeRef = NULL; +xmlNodePtr xmlNodeAdrPtr = NULL; +xmlNodePtr xmlNodeRefPtr = NULL; +WsXmlDocH xmlDocResponse = NULL; +xmlDocPtr docPtr = (xmlDocPtr) doc->parserDoc; +WsXmlNsH ns = NULL; +client_opt_t *options = NULL; +filter_t *filter = NULL; +char *enumContext = NULL; +char *query_string = NULL; + +/* Request options and filter */ +options = wsmc_options_init(); + +if (options == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize options")); +goto
[libvirt] [PATCH 11/21] Added implementation for virConnectNumOfDefinedNetworks and virConnectListDefinedNetworks
From: yvinter --- src/hyperv/hyperv_network_driver.c | 81 ++ 1 file changed, 81 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index 84267b7..2063090 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -228,6 +228,85 @@ hypervConnectListNetworks(virConnectPtr conn, char **const names, int maxnames) +static int +hypervConnectNumOfDefinedNetworks(virConnectPtr conn) +{ +int result = -1, count = 0; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSwitch *virtualSwitchList = NULL; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where HealthState <> %d", 5); +if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) { +goto cleanup; +} + +for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL; + virtualSwitch = virtualSwitch->next) { +count++; +} + +result = count; + + cleanup: +hypervFreeObject(priv, (hypervObject *) virtualSwitchList); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervConnectListDefinedNetworks(virConnectPtr conn, char **const names, int maxnames) +{ +int i, count = 0; +bool success = false; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSwitch *virtualSwitchList = NULL; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +if (maxnames <= 0) +return 0; + +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where HealthState <> %d", 5); +if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) { +goto cleanup; +} + +for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL; + virtualSwitch = virtualSwitch->next) { +if (VIR_STRDUP(names[count], virtualSwitch->data->ElementName) < 0) { +goto cleanup; +} +count++; +if (count >= maxnames) { +break; +} +} + +success = true; + + cleanup: +if (!success) { +for (i = 0; i < count; ++i) { +VIR_FREE(names[i]); +} +count = -1; +} + +hypervFreeObject(priv, (hypervObject *) virtualSwitchList); +virBufferFreeAndReset(&query); + +return count; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ @@ -236,6 +315,8 @@ static virNetworkDriver hypervNetworkDriver = { .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.10 */ .connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.10 */ .connectListNetworks = hypervConnectListNetworks, /* 1.2.10 */ +.connectNumOfDefinedNetworks = hypervConnectNumOfDefinedNetworks, /* 1.2.10 */ +.connectListDefinedNetworks = hypervConnectListDefinedNetworks, /* 1.2.10 */ }; -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 13/21] Added implementation for virDomainSetAutostart and virDomainGetAutostart (required Msvm_VirtualSystemManagementService and Msvm_VirtualSystemGlobalSettingData classes)
From: yvinter --- src/hyperv/hyperv_driver.c| 103 ++ src/hyperv/hyperv_wmi.c | 6 -- src/hyperv/hyperv_wmi.h | 7 +++ src/hyperv/hyperv_wmi_generator.input | 50 + 4 files changed, 160 insertions(+), 6 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 4074fb0..5c79c99 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1908,6 +1908,107 @@ hypervDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams) +static int +hypervDomainSetAutostart(virDomainPtr domain, int autostart) +{ +int result = -1; +invokeXmlParam *params = NULL; +hypervPrivate *priv = domain->conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +virBuffer queryVssd = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +properties_t *tab_props = NULL; +eprParam eprparam; +embeddedParam embeddedparam; +int nb_params; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService"; + +virUUIDFormat(domain->uuid, uuid_string); + +/* Prepare EPR param */ +virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT); +virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string); +eprparam.query = &query; +eprparam.wmiProviderURI = ROOT_VIRTUALIZATION; + +/* Prepare EMBEDDED param */ +virBufferAsprintf(&queryVssd, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); + +if (hypervGetMsvmVirtualSystemSettingDataList(priv, &queryVssd, &virtualSystemSettingData) < 0) +goto cleanup; + +embeddedparam.nbProps = 2; +if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0) +goto cleanup; +(*tab_props).name = "AutomaticStartupAction"; +(*tab_props).val = autostart ? "2" : "0"; +(*(tab_props+1)).name = "InstanceID"; +(*(tab_props+1)).val = virtualSystemSettingData->data->InstanceID; + +embeddedparam.instanceName = "Msvm_VirtualSystemGlobalSettingData"; +embeddedparam.prop_t = tab_props; + +/* Create invokeXmlParam tab */ +nb_params = 2; +if (VIR_ALLOC_N(params, nb_params) < 0) +goto cleanup; +(*params).name = "ComputerSystem"; +(*params).type = EPR_PARAM; +(*params).param = &eprparam; +(*(params+1)).name = "SystemSettingData"; +(*(params+1)).type = EMBEDDED_PARAM; +(*(params+1)).param = &embeddedparam; + +result = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystem", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector); + + cleanup: +hypervFreeObject(priv, (hypervObject *) virtualSystemSettingData); +VIR_FREE(tab_props); +VIR_FREE(params); +virBufferFreeAndReset(&query); +virBufferFreeAndReset(&queryVssd); + +return result; +} + + + +static int +hypervDomainGetAutostart(virDomainPtr domain, int *autostart) +{ +int result = -1; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSystemGlobalSettingData *vsgsd = NULL; + +virUUIDFormat(domain->uuid, uuid_string); +virBufferAddLit(&query, MSVM_VIRTUALSYSTEMGLOBALSETTINGDATA_WQL_SELECT); +virBufferAsprintf(&query, "where SystemName = \"%s\"", uuid_string); + +if (hypervGetMsvmVirtualSystemGlobalSettingDataList(priv, &query, &vsgsd) < 0) +goto cleanup; + +*autostart = vsgsd->data->AutomaticStartupAction; +result = 0; + + cleanup: +hypervFreeObject(priv, (hypervObject *) vsgsd); +virBufferFreeAndReset(&query); + +return result; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1955,6 +2056,8 @@ static virDriver hypervDriver = { .domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /* 1.2.10 */ .domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.10 */ .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.10 */ +.domainSetAutostart = hypervDomainSetAutostart, /* 1.2.10 */ +.domainGetAutostart = hypervDomainGetAutostart, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index 61fb540..f086843 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -37,12 +37,6 @@ #define WS_SERIALIZER_FREE_MEM_WORKS 0 -#define ROOT_CIMV2 \ -"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"; - -#define ROOT_VIRTUA
[libvirt] [PATCH 04/21] Added implementation for virDomainGetVcpus and virConnectGetMaxVcpus (required Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor class)
From: yvinter --- src/hyperv/hyperv_driver.c| 184 ++ src/hyperv/hyperv_wmi_generator.input | 109 2 files changed, 293 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index dd56fb0..f734c09 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1532,6 +1532,186 @@ hypervConnectGetCapabilities(virConnectPtr conn) +static int +hypervConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) +{ +int result = -1; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_ProcessorSettingData *processorSettingData = NULL; + +/* Get Msvm_ProcessorSettingData maximum definition */ +virBufferAddLit(&query, "SELECT * FROM Msvm_ProcessorSettingData " +"WHERE InstanceID LIKE 'Microsoft:Definition%Maximum'"); + +if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) { +goto cleanup; +} + +if (processorSettingData == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get maximum definition of Msvm_ProcessorSettingData")); +goto cleanup; +} + +result = processorSettingData->data->SocketCount * processorSettingData->data->ProcessorsPerSocket; + + cleanup: +hypervFreeObject(priv, (hypervObject *) processorSettingData); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) +{ +int result = -1; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = domain->conn->privateData; +Msvm_ComputerSystem *computerSystem = NULL; +Msvm_ProcessorSettingData *processorSettingData = NULL; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +virBuffer query = VIR_BUFFER_INITIALIZER; + +virCheckFlags(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM, -1); + +virUUIDFormat(domain->uuid, uuid_string); + +/* Get Msvm_ComputerSystem */ +if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) { +goto cleanup; +} + +/* If @flags includes VIR_DOMAIN_VCPU_LIVE, + this will query a running domain (which will fail if domain is not active) */ +if (flags & VIR_DOMAIN_VCPU_LIVE) { +if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) { +virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not active")); +goto cleanup; +} +} + +/* If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then the maximum virtual CPU limit is queried */ +if (flags & VIR_DOMAIN_VCPU_MAXIMUM) { +result = hypervConnectGetMaxVcpus(domain->conn, NULL); +goto cleanup; +} + +/* Get Msvm_VirtualSystemSettingData */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); +if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) { +goto cleanup; +} +if (virtualSystemSettingData == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", computerSystem->data->ElementName); +goto cleanup; +} + +/* Get Msvm_ProcessorSettingData */ +virBufferFreeAndReset(&query); +virBufferAsprintf(&query, + "associators of " + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " + "where AssocClass = Msvm_VirtualSystemSettingDataComponent " + "ResultClass = Msvm_ProcessorSettingData", + virtualSystemSettingData->data->InstanceID); +if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) { +goto cleanup; +} +if (processorSettingData == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), + "Msvm_ProcessorSettingData", computerSystem->data->ElementName); +goto cleanup; +} + +result = processorSettingData->data->VirtualQuantity; + + cleanup: +hypervFreeObject(priv, (hypervObject *)computerSystem); +hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); +hypervFreeObject(priv, (hypervObject *)processorSettingData); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervDomainGetMaxVcpus(virDomainPtr dom) +{ +/* If t
[libvirt] [PATCH 02/21] Added implementation for virConnectGetVersion (required CIM_DataFile class)
From: yvinter --- src/hyperv/hyperv_driver.c| 55 +++ src/hyperv/hyperv_wmi_generator.input | 37 +++ src/hyperv/hyperv_wmi_generator.py| 4 +-- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 372ff39..f2017c3 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1232,6 +1232,7 @@ hypervDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags) } + #define MATCH(FLAG) (flags & (FLAG)) static int hypervConnectListAllDomains(virConnectPtr conn, @@ -1366,6 +1367,59 @@ hypervConnectListAllDomains(virConnectPtr conn, +static int +hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) +{ +int result = -1; +hypervPrivate *priv = conn->privateData; +CIM_DataFile *datafile = NULL; +virBuffer query = VIR_BUFFER_INITIALIZER; +char *p; + +virBufferAddLit(&query, " Select * from CIM_DataFile where Name='c:windowssystem32vmms.exe' "); +if (hypervGetCIMDataFileList(priv, &query, &datafile) < 0) { +goto cleanup; +} + +/* Check the result of convertion */ +if (datafile == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", + datafile->data->Version); +goto cleanup; +} + +/* Delete release number and last digit of build number 1.1.111x. */ +p = strrchr(datafile->data->Version,'.'); +if (p == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not parse version number from '%s'"), + datafile->data->Version); +goto cleanup; +} +p--; +*p = '\0'; + +/* Parse Version String to Long */ +if (virParseVersionString(datafile->data->Version, + version, true) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not parse version number from '%s'"), + datafile->data->Version); +goto cleanup; +} + +result = 0; + + cleanup: +hypervFreeObject(priv, (hypervObject *)datafile); +virBufferFreeAndReset(&query); + +return result; +} + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1402,6 +1456,7 @@ static virDriver hypervDriver = { .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ +.connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 97f9dff..6b969df 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -296,3 +296,40 @@ class Win32_Processor string Version uint32 VoltageCaps end + + +class CIM_DataFile + uint32 AccessMask + boolean Archive + string Caption + boolean Compressed + string CompressionMethod + string CreationClassName + datetime CreationDate + string CSCreationClassName + string CSName + string Description + string Drive + string EightDotThreeFileName + boolean Encrypted + string EncryptionMethod + string Extension + string FileName + uint64 FileSize + string FileType + string FSCreationClassName + string FSName + boolean Hidden + datetime InstallDate + uint64 InUseCount + datetime LastAccessed + datetime LastModified + string Manufacturer + string Name + string Path + boolean Readable + string Status + boolean System + string Version + boolean Writeable +end diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index f767d54..1011719 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -68,7 +68,7 @@ class Class: header += "\n" header += "#define %s_RESOURCE_URI \\\n" % name_upper -if self.name.startswith("Win32_"): +if self.name.startswith("Win32_") or self.name.startswith("CIM_DataFile"): header += " \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/%s\"\n"; % self.name else: header += " \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/%s\"\n"; % self.name @@ -113,7 +113,7 @@ class Class: % (self.name.replace("_", ""), self.name) source += "{\n" -if self.name.startswith("Win32_"): +if self.name.startswith("Win32_") or self.name.startswith("CIM_DataFile"):
[libvirt] [PATCH 10/21] Added implementation for virConnectNumOfNetworks and virConnectListNetworks
From: yvinter --- src/hyperv/hyperv_network_driver.c | 81 ++ 1 file changed, 81 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index ee7c0b3..84267b7 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -149,12 +149,93 @@ hypervNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags) +static int +hypervConnectNumOfNetworks(virConnectPtr conn) +{ +int result = -1, count = 0; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSwitch *virtualSwitchList = NULL; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where HealthState = %d", 5); +if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) { +goto cleanup; +} + +for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL; + virtualSwitch = virtualSwitch->next) { +count++; +} + +result = count; + + cleanup: +hypervFreeObject(priv, (hypervObject *) virtualSwitchList); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervConnectListNetworks(virConnectPtr conn, char **const names, int maxnames) +{ +int i, count = 0; +bool success = false; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSwitch *virtualSwitchList = NULL; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +if (maxnames <= 0) +return 0; + +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where HealthState = %d", 5); +if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitchList) < 0) { +goto cleanup; +} + +for (virtualSwitch = virtualSwitchList; virtualSwitch != NULL; + virtualSwitch = virtualSwitch->next) { +if (VIR_STRDUP(names[count], virtualSwitch->data->ElementName) < 0) { +goto cleanup; +} +count++; +if (count >= maxnames) { +break; +} +} + +success = true; + + cleanup: +if (!success) { +for (i = 0; i < count; ++i) { +VIR_FREE(names[i]); +} +count = -1; +} + +hypervFreeObject(priv, (hypervObject *) virtualSwitchList); +virBufferFreeAndReset(&query); + +return count; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ .networkClose = hypervNetworkClose, /* 0.9.5 */ .networkLookupByName = hypervNetworkLookupByName, /* 1.2.10 */ .networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.10 */ +.connectNumOfNetworks = hypervConnectNumOfNetworks, /* 1.2.10 */ +.connectListNetworks = hypervConnectListNetworks, /* 1.2.10 */ }; -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 09/21] Added implementation for virNetworkGetXMLDesc
From: yvinter --- src/hyperv/hyperv_network_driver.c | 57 ++ 1 file changed, 57 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index 22e1144..ee7c0b3 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -27,8 +27,10 @@ #include "datatypes.h" #include "viralloc.h" #include "viruuid.h" +#include "virstring.h" #include "hyperv_network_driver.h" #include "hyperv_wmi.h" +#include "network_conf.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -93,11 +95,66 @@ hypervNetworkLookupByName(virConnectPtr conn, const char *name) +static char * +hypervNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags) +{ +char *xml = NULL; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +hypervPrivate *priv = network->conn->privateData; +virNetworkDefPtr def = NULL; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +/* Flags checked by virNetworkDefFormat */ + +if (VIR_ALLOC(def) < 0) { +virReportOOMError(); +goto cleanup; +} + +virUUIDFormat(network->uuid, uuid_string); + +/* Get Msvm_VirtualSwitch */ +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string); +if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) { +goto cleanup; +} +if (virtualSwitch == NULL) { +virReportError(VIR_ERR_NO_NETWORK, + _("No network found with UUID %s"), uuid_string); +goto cleanup; +} + +/* Fill struct */ +if (virUUIDParse(virtualSwitch->data->Name, def->uuid) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not parse UUID from string '%s'"), + virtualSwitch->data->Name); +return NULL; +} + +if (VIR_STRDUP(def->name, virtualSwitch->data->ElementName) < 0) +goto cleanup; + +xml = virNetworkDefFormat(def, flags); + + cleanup: +virNetworkDefFree(def); +hypervFreeObject(priv, (hypervObject *)virtualSwitch); +virBufferFreeAndReset(&query); + +return xml; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ .networkClose = hypervNetworkClose, /* 0.9.5 */ .networkLookupByName = hypervNetworkLookupByName, /* 1.2.10 */ +.networkGetXMLDesc = hypervNetworkGetXMLDesc, /* 1.2.10 */ }; -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 03/21] Added basic implementation for virConnectGetCapabilities (required Win32_ComputerSystemProduct class)
From: yvinter --- src/hyperv/hyperv_driver.c| 112 ++ src/hyperv/hyperv_private.h | 2 + src/hyperv/hyperv_wmi_generator.input | 12 3 files changed, 126 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f2017c3..dd56fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -58,12 +58,19 @@ hypervFreePrivate(hypervPrivate **priv) wsmc_release((*priv)->client); } +if ((*priv)->caps != NULL) +virObjectUnref((*priv)->caps); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } +/* Forward declaration of hypervCapsInit */ +static virCapsPtr hypervCapsInit(hypervPrivate *priv); + + static virDrvOpenStatus hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) { @@ -192,6 +199,12 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags goto cleanup; } +/* Setup capabilities */ +priv->caps = hypervCapsInit(priv); +if (priv->caps == NULL) { +goto cleanup; +} + conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; @@ -1420,6 +1433,104 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version) } +/* Retrieves host system UUID */ +static int +hypervLookupHostSystemBiosUuid(hypervPrivate *priv, unsigned char *uuid) +{ +Win32_ComputerSystemProduct *computerSystem = NULL; +virBuffer query = VIR_BUFFER_INITIALIZER; +int result = -1; + +virBufferAddLit(&query, WIN32_COMPUTERSYSTEMPRODUCT_WQL_SELECT); + +if (hypervGetWin32ComputerSystemProductList(priv, &query, &computerSystem) < 0) { +goto cleanup; +} + +if (computerSystem == NULL) { +virReportError(VIR_ERR_NO_DOMAIN, + _("Unable to get Win32_ComputerSystemProduct")); +goto cleanup; +} + +if (virUUIDParse(computerSystem->data->UUID, uuid) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not parse UUID from string '%s'"), + computerSystem->data->UUID); +goto cleanup; +} + +result = 0; + + cleanup: +hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); + +return result; +} + + + +static virCapsPtr hypervCapsInit(hypervPrivate *priv) +{ +virCapsPtr caps = NULL; +virCapsGuestPtr guest = NULL; + +caps = virCapabilitiesNew(VIR_ARCH_X86_64, 1, 1); + +if (caps == NULL) { +virReportOOMError(); +return NULL; +} + +/* virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 }); */ + +if (hypervLookupHostSystemBiosUuid(priv,caps->host.host_uuid) < 0) { +goto failure; +} + +/* i686 */ +guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, NULL, NULL, 0, NULL); +if (guest == NULL) { +goto failure; +} +if (virCapabilitiesAddGuestDomain(guest, "hyperv", NULL, NULL, 0, NULL) == NULL) { +goto failure; +} + +/* x86_64 */ +guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, NULL, NULL, 0, NULL); +if (guest == NULL) { +goto failure; +} +if (virCapabilitiesAddGuestDomain(guest, "hyperv", NULL, NULL, 0, NULL) == NULL) { +goto failure; +} + +return caps; + + failure: +virObjectUnref(caps); +return NULL; +} + + + +static char* +hypervConnectGetCapabilities(virConnectPtr conn) +{ +hypervPrivate *priv = conn->privateData; +char *xml = virCapabilitiesFormatXML(priv->caps); + +if (xml == NULL) { +virReportOOMError(); +return NULL; +} + +return xml; +} + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, @@ -1457,6 +1568,7 @@ static virDriver hypervDriver = { .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */ +.connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h index 574bb5f..d9aa0bd 100644 --- a/src/hyperv/hyperv_private.h +++ b/src/hyperv/hyperv_private.h @@ -26,6 +26,7 @@ # include "internal.h" # include "virerror.h" # include "hyperv_util.h" +# include "capabilities.h" # include "openwsman.h" typedef struct _hypervPrivate hypervPrivate; @@ -33,6 +34,7 @@ typedef struct _hypervPrivate hypervPrivate; struct _hypervPrivate { hypervParsedUri *parsedUri; WsManClient *client; +virCapsPtr caps; }; #endif /* __HYPERV_PRIVATE_H__ */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 6b969df..f1e0c81 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.in
[libvirt] [PATCH 05/21] Added implementation for virNodeGetFreeMemory (required Win32_OperatingSystem class)
From: yvinter --- src/hyperv/hyperv_driver.c| 34 ++ src/hyperv/hyperv_wmi_generator.input | 68 +++ src/hyperv/hyperv_wmi_generator.py| 1 + 3 files changed, 103 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index f734c09..191c7dd 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1712,6 +1712,39 @@ hypervDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, +static unsigned long long +hypervNodeGetFreeMemory(virConnectPtr conn) +{ +unsigned long long res = 0; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Win32_OperatingSystem *operatingSystem = NULL; + +/* Get Win32_OperatingSystem */ +virBufferAddLit(&query, WIN32_OPERATINGSYSTEM_WQL_SELECT); + +if (hypervGetWin32OperatingSystemList(priv, &query, &operatingSystem) < 0) { +goto cleanup; +} + +if (operatingSystem == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get Win32_OperatingSystem")); +goto cleanup; +} + +/* Return free memory in bytes */ +res = operatingSystem->data->FreePhysicalMemory * 1024; + + cleanup: +hypervFreeObject(priv, (hypervObject *) operatingSystem); +virBufferFreeAndReset(&query); + +return res; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1753,6 +1786,7 @@ static virDriver hypervDriver = { .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.10 */ .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */ .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */ +.nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 8fb34e4..739be87 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -454,3 +454,71 @@ class Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor uint64 VirtualMMUHypercallsPersec uint64 VirtualProcessorHypercallsPersec end + + +class Win32_OperatingSystem + string BootDevice + string BuildNumber + string BuildType + string Caption + string CodeSet + string CountryCode + string CreationClassName + string CSCreationClassName + string CSDVersion + string CSName + sint16 CurrentTimeZone + boolean DataExecutionPrevention_Available + boolean DataExecutionPrevention_32BitApplications + boolean DataExecutionPrevention_Drivers + uint8DataExecutionPrevention_SupportPolicy + boolean Debug + string Description + boolean Distributed + uint32 EncryptionLevel + uint8ForegroundApplicationBoost + uint64 FreePhysicalMemory + uint64 FreeSpaceInPagingFiles + uint64 FreeVirtualMemory + datetime InstallDate + uint32 LargeSystemCache + datetime LastBootUpTime + datetime LocalDateTime + string Locale + string Manufacturer + uint32 MaxNumberOfProcesses + uint64 MaxProcessMemorySize + string MUILanguages[] + string Name + uint32 NumberOfLicensedUsers + uint32 NumberOfProcesses + uint32 NumberOfUsers + uint32 OperatingSystemSKU + string Organization + string OSArchitecture + uint32 OSLanguage + uint32 OSProductSuite + uint16 OSType + string OtherTypeDescription + boolean PAEEnabled + string PlusProductID + string PlusVersionNumber + boolean PortableOperatingSystem + boolean Primary + uint32 ProductType + string RegisteredUser + string SerialNumber + uint16 ServicePackMajorVersion + uint16 ServicePackMinorVersion + uint64 SizeStoredInPagingFiles + string Status + uint32 SuiteMask + string SystemDevice + string SystemDirectory + string SystemDrive + uint64 TotalSwapSpaceSize + uint64 TotalVirtualMemorySize + uint64 TotalVisibleMemorySize + string Version + string WindowsDirectory +end diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 1011719..5010470 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -158,6 +158,7 @@ class Property: "int16": "INT16", "int32": "INT32", "int64": "INT64", + "sint16" : "INT16", "uint8": "UINT8", "uint16" : "UINT16", "uint32" : "UINT32", -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/lis
[libvirt] [PATCH 07/21] Added implementation for virDomainGetSchedulerType and virDomainGetSchedulerParameters
From: yvinter --- src/hyperv/hyperv_driver.c | 129 + 1 file changed, 129 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index aadadb1..4074fb0 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -41,6 +41,7 @@ #include "hyperv_wmi.h" #include "openwsman.h" #include "virstring.h" +#include "virtypedparam.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -1782,6 +1783,131 @@ hypervDomainShutdown(virDomainPtr dom) +static int +hypervDomainGetSchedulerParametersFlags(virDomainPtr dom, virTypedParameterPtr params, +int *nparams, unsigned int flags) +{ +hypervPrivate *priv = dom->conn->privateData; +Msvm_ComputerSystem *computerSystem = NULL; +Msvm_ProcessorSettingData *processorSettingData = NULL; +Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL; +char uuid_string[VIR_UUID_STRING_BUFLEN]; +virBuffer query = VIR_BUFFER_INITIALIZER; +int saved_nparams = 0; +int result = -1; + +virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |VIR_DOMAIN_AFFECT_CONFIG |VIR_TYPED_PARAM_STRING_OKAY, -1); + +/* We don't return strings, and thus trivially support this flag */ +flags &= ~VIR_TYPED_PARAM_STRING_OKAY; + +virUUIDFormat(dom->uuid, uuid_string); + +/* Get Msvm_ComputerSystem */ +if (hypervMsvmComputerSystemFromDomain(dom, &computerSystem) < 0) { +goto cleanup; +} + +/* Get Msvm_VirtualSystemSettingData */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where AssocClass = Msvm_SettingsDefineState " + "ResultClass = Msvm_VirtualSystemSettingData", + uuid_string); + +if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) { +goto cleanup; +} + +if (virtualSystemSettingData == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup %s for domain %s"), + "Msvm_VirtualSystemSettingData", + computerSystem->data->ElementName); +goto cleanup; +} + +/* Get Msvm_ProcessorSettingData */ +virBufferAsprintf(&query, + "associators of " + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} " + "where AssocClass = Msvm_VirtualSystemSettingDataComponent " + "ResultClass = Msvm_ProcessorSettingData", + virtualSystemSettingData->data->InstanceID); + +if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) { +goto cleanup; +} + +if (processorSettingData == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"), + "Msvm_ProcessorSettingData",computerSystem->data->ElementName); +goto cleanup; +} + +if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_LIMIT, +VIR_TYPED_PARAM_LLONG, processorSettingData->data->Limit) < 0) +goto cleanup; +saved_nparams++; + +if (*nparams > saved_nparams) { +if (virTypedParameterAssign(¶ms[1],VIR_DOMAIN_SCHEDULER_RESERVATION, +VIR_TYPED_PARAM_LLONG, processorSettingData->data->Reservation) < 0) +goto cleanup; +saved_nparams++; +} + +if (*nparams > saved_nparams) { +if (virTypedParameterAssign(¶ms[2],VIR_DOMAIN_SCHEDULER_WEIGHT, +VIR_TYPED_PARAM_UINT, processorSettingData->data->Weight) < 0) +goto cleanup; +saved_nparams++; +} + +*nparams = saved_nparams; + +result = 0; + + cleanup: +hypervFreeObject(priv, (hypervObject *)computerSystem); +hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); +hypervFreeObject(priv, (hypervObject *)processorSettingData); +virBufferFreeAndReset(&query); + +return result; +} + + + +static int +hypervDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int *nparams) +{ +return hypervDomainGetSchedulerParametersFlags(dom, params, nparams, VIR_DOMAIN_AFFECT_CURRENT); +} + + + +static char* +hypervDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams) +{ +char *type; + +if (VIR_STRDUP(type, "allocation") < 0) { +virReportOOMError(); +return NULL; +} + +if (nparams != NULL) { +*nparams = 3; /* reservation, limit, weight */ +} + +return type; +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1826,6 +1952,9
[libvirt] [PATCH 01/21] Added missing virBufferFreeAndReset on the query buffer to free some memory
From: yvinter --- src/hyperv/hyperv_driver.c | 13 + src/hyperv/hyperv_wmi.c| 15 +++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index aed9307..372ff39 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -201,6 +201,7 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags VIR_FREE(username); VIR_FREE(password); hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); return result; } @@ -254,6 +255,7 @@ hypervConnectGetHostname(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); return hostname; } @@ -352,6 +354,7 @@ hypervNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); hypervFreeObject(priv, (hypervObject *)processorList); +virBufferFreeAndReset(&query); return result; } @@ -396,6 +399,7 @@ hypervConnectListDomains(virConnectPtr conn, int *ids, int maxids) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); +virBufferFreeAndReset(&query); return success ? count : -1; } @@ -432,6 +436,7 @@ hypervConnectNumOfDomains(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); +virBufferFreeAndReset(&query); return success ? count : -1; } @@ -464,6 +469,7 @@ hypervDomainLookupByID(virConnectPtr conn, int id) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); return domain; } @@ -500,6 +506,7 @@ hypervDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); return domain; } @@ -533,6 +540,7 @@ hypervDomainLookupByName(virConnectPtr conn, const char *name) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystem); +virBufferFreeAndReset(&query); return domain; } @@ -748,6 +756,7 @@ hypervDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); hypervFreeObject(priv, (hypervObject *)processorSettingData); hypervFreeObject(priv, (hypervObject *)memorySettingData); +virBufferFreeAndReset(&query); return result; } @@ -915,6 +924,7 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData); hypervFreeObject(priv, (hypervObject *)processorSettingData); hypervFreeObject(priv, (hypervObject *)memorySettingData); +virBufferFreeAndReset(&query); return xml; } @@ -971,6 +981,7 @@ hypervConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxn } hypervFreeObject(priv, (hypervObject *)computerSystemList); +virBufferFreeAndReset(&query); return count; } @@ -1007,6 +1018,7 @@ hypervConnectNumOfDefinedDomains(virConnectPtr conn) cleanup: hypervFreeObject(priv, (hypervObject *)computerSystemList); +virBufferFreeAndReset(&query); return success ? count : -1; } @@ -1346,6 +1358,7 @@ hypervConnectListAllDomains(virConnectPtr conn, } hypervFreeObject(priv, (hypervObject *)computerSystemList); +virBufferFreeAndReset(&query); return ret; } diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index acb705c..d93abd9 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -526,6 +526,7 @@ hypervInvokeMsvmComputerSystemRequestStateChange(virDomainPtr domain, VIR_FREE(returnValue); VIR_FREE(instanceID); hypervFreeObject(priv, (hypervObject *)concreteJob); +virBufferFreeAndReset(&query); return result; } @@ -646,13 +647,14 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain, Msvm_ComputerSystem **computerSystem) { +int result = -1; hypervPrivate *priv = domain->conn->privateData; char uuid_string[VIR_UUID_STRING_BUFLEN]; virBuffer query = VIR_BUFFER_INITIALIZER; if (computerSystem == NULL || *computerSystem != NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); -return -1; +goto cleanup; } virUUIDFormat(domain->uuid, uuid_string); @@ -663,16 +665,21 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain, virBufferAsprintf(&query, "and Name = \"%s\"", uuid_string); if (hypervGetMsvmComputerSystemList(priv, &query, computerSystem) < 0) { -return -1; +goto cleanup; } if (*computerSystem == NULL) { virReportError(VIR_ERR_NO_DOMAIN, _("No domain with UUID %s"), uuid_string); -return -1; +goto c
[libvirt] [PATCH 08/21] Added implementation for virNetworkLookupByName (required Msvm_VirtualSwitch class)
From: yvinter --- src/hyperv/hyperv_network_driver.c| 33 + src/hyperv/hyperv_wmi.c | 27 +++ src/hyperv/hyperv_wmi.h | 9 + src/hyperv/hyperv_wmi_generator.input | 33 + 4 files changed, 102 insertions(+) diff --git a/src/hyperv/hyperv_network_driver.c b/src/hyperv/hyperv_network_driver.c index 6f54f44..22e1144 100644 --- a/src/hyperv/hyperv_network_driver.c +++ b/src/hyperv/hyperv_network_driver.c @@ -28,6 +28,7 @@ #include "viralloc.h" #include "viruuid.h" #include "hyperv_network_driver.h" +#include "hyperv_wmi.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -61,10 +62,42 @@ hypervNetworkClose(virConnectPtr conn) +static virNetworkPtr +hypervNetworkLookupByName(virConnectPtr conn, const char *name) +{ +virNetworkPtr network = NULL; +hypervPrivate *priv = conn->privateData; +virBuffer query = VIR_BUFFER_INITIALIZER; +Msvm_VirtualSwitch *virtualSwitch = NULL; + +virBufferAddLit(&query, MSVM_VIRTUALSWITCH_WQL_SELECT); +virBufferAsprintf(&query, "where Description = \"%s\" and ElementName = \"%s\"", + "Microsoft Virtual Switch", name); +if (hypervGetMsvmVirtualSwitchList(priv, &query, &virtualSwitch) < 0) { +goto cleanup; +} +if (virtualSwitch == NULL) { +virReportError(VIR_ERR_NO_NETWORK, + _("No network found with name %s"), name); +goto cleanup; +} + +hypervMsvmVirtualSwitchToNetwork(conn, virtualSwitch, &network); + + cleanup: +hypervFreeObject(priv, (hypervObject *) virtualSwitch); +virBufferFreeAndReset(&query); + +return network; +} + + + static virNetworkDriver hypervNetworkDriver = { .name = "Hyper-V", .networkOpen = hypervNetworkOpen, /* 0.9.5 */ .networkClose = hypervNetworkClose, /* 0.9.5 */ +.networkLookupByName = hypervNetworkLookupByName, /* 1.2.10 */ }; diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index d93abd9..be84532 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -682,6 +682,33 @@ hypervMsvmComputerSystemFromDomain(virDomainPtr domain, return result; } +int +hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn, + Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr *network) +{ +unsigned char uuid[VIR_UUID_BUFLEN]; + +if (network == NULL || *network != NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); +return -1; +} + +if (virUUIDParse(virtualSwitch->data->Name, uuid) < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not parse UUID from string '%s'"), + virtualSwitch->data->Name); +return -1; +} + +*network = virGetNetwork(conn, virtualSwitch->data->ElementName, uuid); + +if (*network == NULL) { +return -1; +} + +return 0; +} + #include "hyperv_wmi.generated.c" diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h index 5fbbbac..acc4097 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -115,6 +115,15 @@ int hypervMsvmComputerSystemFromDomain(virDomainPtr domain, +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Msvm_VirtualSwitch + */ + +int hypervMsvmVirtualSwitchToNetwork(virConnectPtr conn, + Msvm_VirtualSwitch *virtualSwitch, virNetworkPtr *network); + + + # include "hyperv_wmi.generated.h" #endif /* __HYPERV_WMI_H__ */ diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index 739be87..21420d5 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -522,3 +522,36 @@ class Win32_OperatingSystem string Version string WindowsDirectory end + + +class Msvm_VirtualSwitch + string Caption + string Description + string ElementName + datetime InstallDate + uint16 OperationalStatus[] + string StatusDescriptions[] + string Status + uint16 HealthState + uint16 EnabledState + string OtherEnabledState + uint16 RequestedState + uint16 EnabledDefault + datetime TimeOfLastStateChange + string CreationClassName + string Name + string PrimaryOwnerContact + string PrimaryOwnerName + string Roles[] + string NameFormat + string OtherIdentifyingInfo[] + string IdentifyingDescriptions[] + uint16 Dedicated[] + string OtherDedicatedDescriptions[] + uint16 ResetCapability + uint16 PowerManagementCapabilities[] + string ScopeOfResidence + uint32 NumLearnableAddresses + uint32 MaxVMQOffloads + uint32 MaxChimneyOffloads +end -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat
[libvirt] [PATCH 06/21] Added implementation for virDomainShutdown and virDomainShutdownFlags
From: yvinter --- src/hyperv/hyperv_driver.c | 39 +++ 1 file changed, 39 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 191c7dd..aadadb1 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -1745,6 +1745,43 @@ hypervNodeGetFreeMemory(virConnectPtr conn) +static int +hypervDomainShutdownFlags(virDomainPtr domain, unsigned int flags) +{ +int result = -1; +hypervPrivate *priv = domain->conn->privateData; +Msvm_ComputerSystem *computerSystem = NULL; +bool in_transition = false; + +virCheckFlags(0, -1); + +if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) { +goto cleanup; +} + +if (!hypervIsMsvmComputerSystemActive(computerSystem, &in_transition) || in_transition) { +virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Domain is not active or is in state transition")); +goto cleanup; +} + +result = hypervInvokeMsvmComputerSystemRequestStateChange(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_DISABLED); + + cleanup: +hypervFreeObject(priv, (hypervObject *) computerSystem); +return result; +} + + + +static int +hypervDomainShutdown(virDomainPtr dom) +{ +return hypervDomainShutdownFlags(dom, 0); +} + + + static virDriver hypervDriver = { .no = VIR_DRV_HYPERV, .name = "Hyper-V", @@ -1787,6 +1824,8 @@ static virDriver hypervDriver = { .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */ .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */ .nodeGetFreeMemory = hypervNodeGetFreeMemory, /* 1.2.10 */ +.domainShutdownFlags = hypervDomainShutdownFlags, /* 1.2.10 */ +.domainShutdown = hypervDomainShutdown, /* 1.2.10 */ }; -- 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] security_selinux: Don't relabel /dev/net/tun
On 07.10.2014 17:19, Eric Blake wrote: On 10/07/2014 08:53 AM, Michal Privoznik wrote: https://bugzilla.redhat.com/show_bug.cgi?id=1147057 The code for relabelling the TAP FD is there due to a race. When libvirt creates a /dev/tapN device it's labeled as 'system_u:object_r:device_t:s0' by default. Later, when udev/systemd reacts to this device, it's relabelled to the expected label 'system_u:object_r:tun_tap_device_t:s0'. Hence, we have a code that relabels the device, to cut the race down. For more info see ae368ebfcc4. But the problem is, the relabel function is called on all TUN/TAP devices. Yes, on /dev/net/tun too. This is however a special kind of device - other processes uses it too. We shouldn't touch it's label then. Ideally, there would an API in SELinux that would label just the passed FD and not the underlying path. That way, we wouldn't need to care as we would be not labeling /dev/net/tun but the FD passed to the domain. Unfortunately, there's no such API so we have to workaround until then. + +if (!STRPREFIX(fd_path, "/dev/tap")) { Should this be "/dev/tap.", since... +VIR_DEBUG("fd=%d points to %s not setting SELinux label", + fd, fd_path); +rc = 0; +goto cleanup; +} + if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) { ...you require a '.' in the context lookup? Without the '.' in the filter, you would let the (unlikely) name '/dev/tapX' get through. ACK with that tweaked. In fact, /dev/tapX is what is created. getContext should be using it too as it accepts shell expendable names, not regular expressions. I'm adjusting getContext's argument too. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 2/3] conf: add check if migration_host is a localhost address
On 10/07/2014 06:07 AM, Chen Fan wrote: > Signed-off-by: Chen Fan > --- > src/libvirt_private.syms | 1 + > src/qemu/qemu_conf.c | 50 > > src/qemu/qemu_conf.h | 2 ++ > src/util/virsocketaddr.c | 24 +++ > src/util/virsocketaddr.h | 2 ++ > 5 files changed, 79 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 8ab1394..a104bc6 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1911,6 +1911,7 @@ virSocketAddrGetIpPrefix; > virSocketAddrGetPort; > virSocketAddrGetRange; > virSocketAddrIsNetmask; > +virSocketAddrIsNumericLocalhost; > virSocketAddrIsPrivate; > virSocketAddrIsWildcard; > virSocketAddrMask; > diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c > index adc6caf..6b0ac5c 100644 > --- a/src/qemu/qemu_conf.c > +++ b/src/qemu/qemu_conf.c > @@ -707,6 +707,15 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr > cfg, > GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); > > GET_VALUE_STR("migration_host", cfg->migrateHost); > +if (cfg->migrateHost && > +qemuCheckLocalhost(cfg->migrateHost)) { > +virReportError(VIR_ERR_CONF_SYNTAX, > + _("migration_host must not be the address of" > + " the local machine: %s"), > + cfg->migrateHost); > +goto cleanup; > +} > + > GET_VALUE_STR("migration_address", cfg->migrationAddress); > > GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); > @@ -1371,3 +1380,44 @@ qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, > > return qemuGetHugepagePath(&hugetlbfs[i]); > } > + > +bool > +qemuCheckLocalhost(const char *addrStr) > +{ > +virSocketAddr addr; > +char *hostname, *tmp; > +bool encloseAddress = false; > +int family; > +bool ret = true; > + > +if (VIR_STRDUP(hostname, addrStr) < 0) > +return false; > + > +tmp = hostname; > + > +if (STRPREFIX(hostname, "[")) { > +char *end = strchr(hostname, ']'); > +if (end) { > +*end = '\0'; > +hostname++; > +encloseAddress = true; > +} > +} We don't format the qemu.conf back and we don't need the brackets for anything. We can just store the migration host without them in cfg->migrationHost > + > +if (STRPREFIX(hostname, "localhost")) > +goto cleanup; > + > +family = virSocketAddrNumericFamily(hostname); > +if ((family == AF_INET && !encloseAddress) || > +family == AF_INET6) { > +if (virSocketAddrParse(&addr, hostname, family) > 0 && > +virSocketAddrIsNumericLocalhost(&addr)) { > +goto cleanup; > +} > +} There's no need to check for family upfront. > + > +ret = false; > +cleanup: > +VIR_FREE(tmp); > +return ret; > +} > diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h > index cb01fb6..c9ce53c 100644 > --- a/src/qemu/qemu_conf.h > +++ b/src/qemu/qemu_conf.h > @@ -322,4 +322,6 @@ int qemuTranslateSnapshotDiskSourcePool(virConnectPtr > conn, > char * qemuGetHugepagePath(virHugeTLBFSPtr hugepage); > char * qemuGetDefaultHugepath(virHugeTLBFSPtr hugetlbfs, >size_t nhugetlbfs); > + > +bool qemuCheckLocalhost(const char *addrStr); > #endif /* __QEMUD_CONF_H */ > diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c > index 7fe7a15..6d36689 100644 > --- a/src/util/virsocketaddr.c > +++ b/src/util/virsocketaddr.c > @@ -878,3 +878,27 @@ virSocketAddrNumericFamily(const char *address) > freeaddrinfo(res); > return family; > } > + > +/** > + * virSocketAddrIsNumericLocalhost: > + * @address: address to check > + * > + * Check if passed address is a numeric 'localhost' address. > + * > + * Returns: true if @address is a numeric 'localhost' address, > + * false otherwise > + */ > +bool > +virSocketAddrIsNumericLocalhost(const virSocketAddr *addr) I've rewritten this function to take a 'const char *' argument. Along with the virStringStripIPv6Brackets function I've sent for review separately, this removes the need for a separate qemuCheckLocalhost function and it can be inlined. > +{ > +struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) }; > +switch (addr->data.stor.ss_family) { > +case AF_INET: > +return memcmp(&addr->data.inet4.sin_addr.s_addr, &tmp.s_addr, > + sizeof(addr->data.inet4.sin_addr.s_addr)) == 0; > +case AF_INET6: > +return IN6_IS_ADDR_LOOPBACK(&addr->data.inet6.sin6_addr); > +} > +return false; > + > +} The diff I'll squash into this patch before pushing (after virStringStripIPv6Brackets is sorted out): --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -707,8 +707,10 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox); GET
Re: [libvirt] [PATCH] Introduce virStringStripIPv6Brackets
On 10/08/2014 11:10 AM, Daniel P. Berrange wrote: > On Wed, Oct 08, 2014 at 10:46:53AM +0200, Ján Tomko wrote: >> Helper function to strip the brackets from an IPv6 address. >> Tested by viruritest. >> --- >> src/libvirt_private.syms | 1 + >> src/util/virstring.c | 22 ++ >> src/util/virstring.h | 2 ++ >> src/util/viruri.c| 20 >> 4 files changed, 29 insertions(+), 16 deletions(-) > > Can we have tests in viruritest.c and virstringtest.c too > We already test it on sane inputs in viruritest. I've added some corner cases to virstringtest in v2. > > Regards, > Daniel > signature.asc Description: OpenPGP digital signature -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2] qemu: Pass file descriptor when using TPM passthrough
From: Stefan Berger Pass the TPM file descriptor to QEMU via command line. Instead of passing /dev/tpm0 we now pass /dev/fdset/10 and the additional parameters -add-fd set=10,fd=20. This addresses the use case when QEMU is started with non-root privileges and QEMU cannot open /dev/tpm0 for example. One problem is that for the passing of the file descriptor set to work, virCommandReorderFDs must not be called on the virCommand. This is prevented by setting a flag in the virCommandPassFDGetFDIndex that is checked to be clear when virCommandReorderFDs is run. Signed-off-by: Stefan Berger --- src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 132 --- src/util/vircommand.c| 33 src/util/vircommand.h| 3 ++ 4 files changed, 162 insertions(+), 7 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d6265ac..6c697bb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1158,6 +1158,7 @@ virCommandNewArgList; virCommandNewArgs; virCommandNonblockingFDs; virCommandPassFD; +virCommandPassFDGetFDIndex; virCommandPassListenFDs; virCommandRawStatus; virCommandRequireHandshake; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8cb0865..2e030fb 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -157,6 +157,58 @@ VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST, "interleave"); /** + * qemuVirCommandGetFDSet: + * @cmd: the command to modify + * @fd: fd to reassign to the child + * + * Get the parameters for the QEMU -add-fd command line option + * for the given file descriptor. The file descriptor must previously + * have been 'transferred' in a virCommandPassFD() call. + * This function for example returns "set=10,fd=20". + */ +static char * +qemuVirCommandGetFDSet(virCommandPtr cmd, int fd) +{ +char *result = NULL; +int idx = virCommandPassFDGetFDIndex(cmd, fd); + +if (idx >= 0) { +ignore_value(virAsprintf(&result, "set=%d,fd=%d", idx, fd) < 0); +} else { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("file descriptor %d has not been transferred"), fd); +} + +return result; +} + +/** + * qemuVirCommandGetDevSet: + * @cmd: the command to modify + * @fd: fd to reassign to the child + * + * Get the parameters for the QEMU path= parameter where a file + * descriptor is accessed via a file descriptor set, for example + * /dev/fdset/10. The file descriptor must previously have been + * 'transferred' in a virCommandPassFD() call. + */ +static char * +qemuVirCommandGetDevSet(virCommandPtr cmd, int fd) +{ +char *result = NULL; +int idx = virCommandPassFDGetFDIndex(cmd, fd); + +if (idx >= 0) { +ignore_value(virAsprintf(&result, "/dev/fdset/%d", idx) < 0); +} else { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("file descriptor %d has not been transferred"), fd); +} +return result; +} + + +/** * qemuPhysIfaceConnect: * @def: the definition of the VM (needed by 802.1Qbh and audit) * @driver: pointer to the driver instance @@ -5869,14 +5921,20 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd, static char *qemuBuildTPMBackendStr(const virDomainDef *def, +virCommandPtr cmd, virQEMUCapsPtr qemuCaps, -const char *emulator) +const char *emulator, +int *tpmfd, int *cancelfd) { const virDomainTPMDef *tpm = def->tpm; virBuffer buf = VIR_BUFFER_INITIALIZER; const char *type = virDomainTPMBackendTypeToString(tpm->type); -char *cancel_path; +char *cancel_path = NULL; const char *tpmdev; +char *devset = NULL, *cancel_devset = NULL; + +*tpmfd = -1; +*cancelfd = -1; virBufferAsprintf(&buf, "%s,id=tpm-%s", type, tpm->info.alias); @@ -5889,11 +5947,47 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def, if (!(cancel_path = virTPMCreateCancelPath(tpmdev))) goto error; -virBufferAddLit(&buf, ",path="); -virBufferEscape(&buf, ',', ",", "%s", tpmdev); +if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ADD_FD)) { +*tpmfd = open(tpmdev, O_RDWR); +if (*tpmfd < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not open TPM device %s"), tpmdev); +goto error; +} + +virCommandPassFD(cmd, *tpmfd, + VIR_COMMAND_PASS_FD_CLOSE_PARENT); +devset = qemuVirCommandGetDevSet(cmd, *tpmfd); +if (devset == NULL) +goto error; + +*cancelfd = open(cancel_path, O_WRONLY); +if (*cancelfd < 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, +
[libvirt] [PATCHv2] Introduce virStringStripIPv6Brackets
Helper function to strip the brackets from an IPv6 address. Tested by viruritest. --- src/libvirt_private.syms | 1 + src/util/virstring.c | 22 ++ src/util/virstring.h | 2 ++ src/util/viruri.c| 20 tests/virstringtest.c| 49 5 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d6265ac..c5397dd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2004,6 +2004,7 @@ virStringSortCompare; virStringSortRevCompare; virStringSplit; virStringSplitCount; +virStringStripIPv6Brackets; virStrncpy; virStrndup; virStrToDouble; diff --git a/src/util/virstring.c b/src/util/virstring.c index 54c0b6f..0cb7f3f 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -929,3 +929,25 @@ virStringReplace(const char *haystack, return virBufferContentAndReset(&buf); } + +/** + * virStringStripIPv6Brackets: + * @str: the string to strip + * + * Modify the string in-place to remove the leading and closing brackets + * from an IPv6 address. + */ +void +virStringStripIPv6Brackets(char *str) +{ +size_t len; + +if (!str) +return; + +len = strlen(str); +if (str[0] == '[' && str[len-1] == ']' && strchr(str, ':')) { +memmove(&str[0], &str[1], len - 2); +str[len - 2] = '\0'; +} +} diff --git a/src/util/virstring.h b/src/util/virstring.h index b82ef2a..40ebaeb 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -268,4 +268,6 @@ char *virStringReplace(const char *haystack, const char *newneedle) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +void virStringStripIPv6Brackets(char *str); + #endif /* __VIR_STRING_H__ */ diff --git a/src/util/viruri.c b/src/util/viruri.c index 23d86c5..6166c37 100644 --- a/src/util/viruri.c +++ b/src/util/viruri.c @@ -182,22 +182,10 @@ virURIParse(const char *uri) if (VIR_STRDUP(ret->user, xmluri->user) < 0) goto error; -/* First check: does it even make sense to jump inside */ -if (ret->server != NULL && -ret->server[0] == '[') { -size_t length = strlen(ret->server); - -/* We want to modify the server string only if there are - * square brackets on both ends and inside there is IPv6 - * address. Otherwise we could make a mistake by modifying - * something other than an IPv6 address. */ -if (ret->server[length - 1] == ']' && strchr(ret->server, ':')) { -memmove(&ret->server[0], &ret->server[1], length - 2); -ret->server[length - 2] = '\0'; -} -/* Even after such modification, it is completely ok to free - * the uri with xmlFreeURI() */ -} +/* Strip square bracket from an IPv6 address. + * The function modifies the string in-place. Even after such + * modification, it is OK to free the URI with xmlFreeURI. */ +virStringStripIPv6Brackets(ret->server); if (virURIParseParams(ret) < 0) goto error; diff --git a/tests/virstringtest.c b/tests/virstringtest.c index 10fad2c..841531f 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -522,6 +522,36 @@ testVirStringFreeListCount(const void *opaque ATTRIBUTE_UNUSED) } +struct testStripIPv6BracketsData { +const char *string; +const char *result; +}; + +static int testStripIPv6Brackets(const void *args) +{ +const struct testStripIPv6BracketsData *data = args; +int ret = -1; +char *res = NULL; + +if (VIR_STRDUP(res, data->string) < 0) +goto cleanup; + +virStringStripIPv6Brackets(res); + +if (STRNEQ_NULLABLE(res, data->result)) { +fprintf(stderr, "Returned '%s', expected '%s'\n", +NULLSTR(res), NULLSTR(data->result)); +goto cleanup; +} + +ret = 0; + + cleanup: +VIR_FREE(res); +return ret; +} + + static int mymain(void) { @@ -731,6 +761,25 @@ mymain(void) NULL) < 0) ret = -1; +#define TEST_STRIP_IPV6_BRACKETS(str, res) \ +do {\ +struct testStripIPv6BracketsData stripData = { \ +.string = str, \ +.result = res, \ +}; \ +if (virtTestRun("Strip brackets from IPv6 " #str, \ +testStripIPv6Brackets, &stripData) < 0) \ +ret = -1; \ +} while (0) + +TEST_STRIP_IPV6_BRACKETS(NULL, NULL); +TEST_STRIP_IPV6_BRACKETS("[]", "[]"); +TEST_STRIP_IPV6_BRACKETS("[:]", ":"); +TEST_STRIP_IPV6_BRACKETS("[::1]", "::1"); +TEST_STRIP_IPV6_BRAC
Re: [libvirt] [PATCH] Introduce virStringStripIPv6Brackets
On Wed, Oct 08, 2014 at 10:46:53AM +0200, Ján Tomko wrote: > Helper function to strip the brackets from an IPv6 address. > Tested by viruritest. > --- > src/libvirt_private.syms | 1 + > src/util/virstring.c | 22 ++ > src/util/virstring.h | 2 ++ > src/util/viruri.c| 20 > 4 files changed, 29 insertions(+), 16 deletions(-) Can we have tests in viruritest.c and virstringtest.c too Regards, Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Notes: Non-shared storage live migration w/ active blockcommit
On Tue, Oct 07, 2014 at 05:35:00PM -0600, Eric Blake wrote: > On 09/25/2014 08:26 AM, Kashyap Chamarthy wrote: > > This notes is based on an IRC conversation with Eric Blake, to have > > efficient non-shared storage live migration. Thought I'd post my notes > > here before I forget. Please review and spot if there are any > > inaccuracies. > > > > Procedure > > - > > > > (1) Starting from disk A, create a snapshot A <- A': > > > > $ virsh snapshot-create-as \ > > --domain f20vm snap1 snap1-desc \ > > --diskspec hda,file=/export/vmimages/A'.qcow2 \ > > --disk-only --atomic > > If you are using this snapshot only for the side-effect of growing the > chain, you can add --no-metadata here instead of deleting the snapshot > later when it gets invalidated [1]. Of course, if you pass > --no-metadata, the snapshot name (snap1) and description (snap1-desc) > are no longer important. Right, until proper cleaner revert to external snapshot mechanisms are in place, I should make a habit of passing '--no-metadata' when creating external snapshots for the above reason (as I usually do end up deleting the related libvirt metadata as part of cleanup). > > > > (2) Background copy of A to B: > > > > $ virsh blockcopy \ > > --domain vm1 vda /export/vmimages/B.qcow2 \ > > --wait --verbose --shallow \ > > --finish > > This step is not quite right. You are asking for a shallow copy of the > current file for disk 'vda' (that is, A'.qcow2). But that is NOT the > same as the base A image. Oh right, thanks for catching this mistake. > For this step, libvirt does not yet have an easy way to access the > contents of a backing chain of a live domain; you CAN use 'virsh > vol-*' commands to do a background copy from storage pools, but it may > be easier to just resort to normal file system tools: > > cp /export/vmimages/A.qcow2 /export/vmimages/B.qcow2 Yeah, simple and less commands to type too. > or even rely on storage-array-specific commands to set up a trivial > clone with no real time overhead (for example, some iscsi storage arrays > allow efficient copy-on-write cloning of storage volumes by creating a > new name that shares the same original contents of A.qcow2 as its > starting point; and since we are about to delete A.qcow2 later on, we > never need any actual data copying). > > > > > (3) Create an empty B' with backing file B: > > > > $ qemu-img create -f qcow2 -b B.qcow2 \ > > -o backing_fmt=qcow2 B'.qcow2 > > > > [or] > > > > $ virsh vol-create-as default B'.qcow2 1G \ > > --format qcow2 \ > > --backing-vol B.qcow2 --backing-vol-format qcow2 > > [side note - we should really teach libvirt to not REQUIRE a size when > creating an empty wrapper around an existing image] Filed: https://bugzilla.redhat.com/show_bug.cgi?id=1150411 > > > > (4) Do a shallow blockcopy of A' to B': > > > > $ virsh blockcopy \ > > --domain vm1 vda /export/vmimages/B'.qcow2 \ > > --wait --verbose --shallow \ > > --finish > > For this to work, you need to also use the --reuse-external flag True, I self-corrected in my other response in this thread, but thanks for noticing. > to take > advantage of the backing chain already recorded in B'.qcow2 (without the > flag, the command will complain that B'.qcow2 already exists if it is a > regular file; if it is a block device, it will just silently ignore the > contents of the block device and treat B'.qcow2 as though an absolute > path to A.qcow2 were its backing file). > > > > > (5) Then live shallow commit of B: > > > > $ virsh blockcommit \ > > --domain f20vm vda \ > > --wait --verbose --shallow \ > > --pivot --active --finish > > Block Commit: [100 %] > > Successfully pivoted > > With steps 2 and 4 corrected, this indeed shortens the chain back down > to just B.qcow2. And once this happens, you no longer need the path to > A.qcow2 or A'.qcow2; you can also delete B'.qcow2. But back to the > point I made earlier at [1]: if this is all you do, then 'virsh > snapshot-list' will still show 'snap1' as a snapshot that tries to refer > to A'.qcow2; since you just invalidated that with the copy, you'd need > to 'virsh snapshot-delete --metadata vm1 snap1' to get rid of the stale > snapshot (if you don't tweak step 1 to avoid creating that snapshot > metadata in the first place). Thanks for this reminder, I'll script this as part of my tests to ensure it's not missed. > The NICE part about this whole sequence is that the backing file does > NOT have to be qcow2, and it is VERY efficient timewise, if you happen > to have an efficient way to do step 2. That is, I can go from a > multi-gigabyte raw file A.img to raw file B.img in less than a second, > assuming the guest isn't doing much I/O in the meantime, when scripting > all these steps together, and without any guest downtime. Thanks again, for your met
Re: [libvirt] [PATCH] Introduce virStringStripIPv6Brackets
> -Original Message- > From: libvir-list-boun...@redhat.com [mailto:libvir-list-boun...@redhat.com] > On Behalf Of Ján Tomko > Sent: Wednesday, October 08, 2014 4:47 PM > To: libvir-list@redhat.com > Subject: [libvirt] [PATCH] Introduce virStringStripIPv6Brackets > > Helper function to strip the brackets from an IPv6 address. > Tested by viruritest. Reviewed-by: Chen Hanxiao -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Introduce virStringStripIPv6Brackets
Helper function to strip the brackets from an IPv6 address. Tested by viruritest. --- src/libvirt_private.syms | 1 + src/util/virstring.c | 22 ++ src/util/virstring.h | 2 ++ src/util/viruri.c| 20 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d6265ac..c5397dd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2004,6 +2004,7 @@ virStringSortCompare; virStringSortRevCompare; virStringSplit; virStringSplitCount; +virStringStripIPv6Brackets; virStrncpy; virStrndup; virStrToDouble; diff --git a/src/util/virstring.c b/src/util/virstring.c index 54c0b6f..0cb7f3f 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -929,3 +929,25 @@ virStringReplace(const char *haystack, return virBufferContentAndReset(&buf); } + +/** + * virStringStripIPv6Brackets: + * @str: the string to strip + * + * Modify the string in-place to remove the leading and closing brackets + * from an IPv6 address. + */ +void +virStringStripIPv6Brackets(char *str) +{ +size_t len; + +if (!str) +return; + +len = strlen(str); +if (str[0] == '[' && str[len-1] == ']' && strchr(str, ':')) { +memmove(&str[0], &str[1], len - 2); +str[len - 2] = '\0'; +} +} diff --git a/src/util/virstring.h b/src/util/virstring.h index b82ef2a..40ebaeb 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -268,4 +268,6 @@ char *virStringReplace(const char *haystack, const char *newneedle) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +void virStringStripIPv6Brackets(char *str); + #endif /* __VIR_STRING_H__ */ diff --git a/src/util/viruri.c b/src/util/viruri.c index 23d86c5..6166c37 100644 --- a/src/util/viruri.c +++ b/src/util/viruri.c @@ -182,22 +182,10 @@ virURIParse(const char *uri) if (VIR_STRDUP(ret->user, xmluri->user) < 0) goto error; -/* First check: does it even make sense to jump inside */ -if (ret->server != NULL && -ret->server[0] == '[') { -size_t length = strlen(ret->server); - -/* We want to modify the server string only if there are - * square brackets on both ends and inside there is IPv6 - * address. Otherwise we could make a mistake by modifying - * something other than an IPv6 address. */ -if (ret->server[length - 1] == ']' && strchr(ret->server, ':')) { -memmove(&ret->server[0], &ret->server[1], length - 2); -ret->server[length - 2] = '\0'; -} -/* Even after such modification, it is completely ok to free - * the uri with xmlFreeURI() */ -} +/* Strip square bracket from an IPv6 address. + * The function modifies the string in-place. Even after such + * modification, it is OK to free the URI with xmlFreeURI. */ +virStringStripIPv6Brackets(ret->server); if (virURIParseParams(ret) < 0) goto error; -- 2.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [Question] capabilities.pidfile is left behind while starting and stopping libvirtd repeatly
On 2014/10/2 17:55, Martin Kletzander wrote: > On Tue, Sep 30, 2014 at 10:26:21PM +0200, Guido Günther wrote: >> On Tue, Sep 30, 2014 at 04:47:14PM +0200, Martin Kletzander wrote: >>> On Tue, Sep 30, 2014 at 05:34:54PM +0800, Wang Yufei wrote: >>> >Hi, all >>> > >>> >I started and stopped libvirtd service repeatly with high frequency(1 per >>> >second), and found that the file capabilities.pidfile is left behind, as >>> >well as a qemu process. If I then restart libvirtd, qemu-kvm will fail to >>> >start as it's unable to flock capabilities.pidfile's fd. >>> > >>> >>> Have you tried current master? Or at least -rc2? It should already >>> be fixed there: >>> >>> commit 9e159b521dbf18c6da6976e54e29c8553f831eb6 >>> Author: Guido Günther >>> Date: Thu Sep 25 10:30:58 2014 +0200 >>> >>>qemu: remove capabilities.monitor.sock when done >>> >> >> This one removes the monitor socket, not the pidfile since I didn't >> see that one lingering around in my tests. >> Cheers, > > Oh, sorry for that, my fault. Well, should the daemon just kill the > process when it's dying in order to release the lock? If you try > slower, we will properly remove the pidfile, won't we? Yes, the pidfile will be keep open and locked forever if this qemu process is alive. And it will be unlink if I shutdown libvitd daemon slower. But in this condition(started and stopped libvirtd service repeatly with high frequency) the pidfile is left behind. In fact libvirtd daemon is killed before qemu-kvm process and pidfile are cleaned up. Is it a problem? -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Features - virDomainOpenConsole
2014-10-06 19:56 GMT+02:00 Andre Smith : > Hi, > > We urgently need proper virDomainOpenConsole support for both VMware and > Virtualbox. Since this is for our own commercial usage, my employer has > authorized me to find a developer that can do the work quickly and properly > and to pay them for their efforts. About which VMware products are you talking here? vSphere/ESX or Workstation/Player/Fusion? -- Matthias Bolte http://photron.blogspot.com -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] "pclmuldq" was introduced with Westmere, not Sandy Bridge. This feature is important to get proper performance for aes-128-gcm in openssl, an important cipher for https communica
On Tue, Oct 07, 2014 at 21:22:12 +0200, Jan-Frode Myklebust wrote: > > Signed-off-by: Jan-Frode Myklebust > --- > src/cpu/cpu_map.xml |2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml > index 18c7b0d..94f1458 100644 > --- a/src/cpu/cpu_map.xml > +++ b/src/cpu/cpu_map.xml > @@ -488,11 +488,11 @@ > > > > + > > > > > - > > > Technically you are correct and even QEMU added this feature to Westmere in April 2013. However, our goal is to provide stable virtual hardware that doesn't change when, e.g., a domain is migrated to another machine (let's ignore the fact we don't currently enforce such stability for CPU models/features because of missing functionality in both QEMU and libvirt). Thus we should not really change existing CPU models. We may be able to do that in the future depending how (if ever) we solve the CPU definition probing in QEMU and how libvirt will make use of it to really enforce stable ABI for guest operating systems. Moreover, it's trivial to enable the feature in domain XML: Westmere That said, I don't think we should take this patch, at least not for now. Jirka -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix build with older libcurl
2014-10-08 9:15 GMT+02:00 Ján Tomko : > Add ATTRIBUTE_UNUSED marker to the unused timeout_ms option > in esxVI_MultiCURL_TimerCallback. > > Introduced by commit 125007d. > --- > Pushed under the build breaker rule. > > src/esx/esx_vi.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c > index fcd2e70..b00d8e7 100644 > --- a/src/esx/esx_vi.c > +++ b/src/esx/esx_vi.c > @@ -711,7 +711,8 @@ esxVI_MultiCURL_SocketCallback(CURL *handle > ATTRIBUTE_UNUSED, > > static int > esxVI_MultiCURL_TimerCallback(CURLM *handle ATTRIBUTE_UNUSED, > - long timeout_ms, void *callback_opaque) > + long timeout_ms ATTRIBUTE_UNUSED, > + void *callback_opaque) > { > esxVI_MultiCURL *multi = callback_opaque; Ah, I probably didn't do final test with libcurl < 7.28.0 yesterday. Sorry and thanks for fixing this. -- Matthias Bolte http://photron.blogspot.com -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Fix build with older libcurl
Add ATTRIBUTE_UNUSED marker to the unused timeout_ms option in esxVI_MultiCURL_TimerCallback. Introduced by commit 125007d. --- Pushed under the build breaker rule. src/esx/esx_vi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index fcd2e70..b00d8e7 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -711,7 +711,8 @@ esxVI_MultiCURL_SocketCallback(CURL *handle ATTRIBUTE_UNUSED, static int esxVI_MultiCURL_TimerCallback(CURLM *handle ATTRIBUTE_UNUSED, - long timeout_ms, void *callback_opaque) + long timeout_ms ATTRIBUTE_UNUSED, + void *callback_opaque) { esxVI_MultiCURL *multi = callback_opaque; -- 2.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list