[libvirt] [PATCH 0/4] Updated patches 2-6 - virInterface test driver and netcf backend
These patches correspond to patches 2-6 in the set I sent yesterday (the 1st and 2nd had no changes, so they stand as-is). They incorporate all changes brought up in review of the first set. In particular: 1) When looking for a cached virInterface object for an interface, I now check that the mac address being searched for matches the one in the virInterface (case insensitive comparison). If it doesn't match, I create a new object rather than trying to modify the existing object with the same interface name, as that could have led to improper behavior. 2) in virInterfaceFindByMACString() I now follow danpb's suggestion and use continue, rather than getting fancy with booleans. 3) testinterfaceCreate() and testInterfaceDestroy() now check if the interface has already been created/destroyed, and won't do the same operation twice in a row. 4) in the netcf backend driver, I now roundtrip the xml data in both interfaceDefineXML() and interfaceGetXMLDesc(). -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/4] Match MAC address as well as interface name in virGetinterface.
MAC address of a particular interface may change over time, and the reduced virInterface object (which contains just name and mac) needs to reflect these changes. Since we can't modify the mac address of an existing virInterface (some other thread may currently be using it) we just create a new virInterface, and let the old one die a dignified death when its refct goes to 0. --- src/datatypes.c | 14 ++ 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/datatypes.c b/src/datatypes.c index a8bffd2..5f90aad 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -516,9 +516,10 @@ virUnrefNetwork(virNetworkPtr network) { * @mac: pointer to the mac * * Lookup if the interface is already registered for that connection, - * if yes return a new pointer to it, if no allocate a new structure, - * and register it in the table. In any case a corresponding call to - * virUnrefInterface() is needed to not leak data. + * if yes return a new pointer to it (possibly updating the MAC + * address), if no allocate a new structure, and register it in the + * table. In any case a corresponding call to virUnrefInterface() is + * needed to not leak data. * * Returns a pointer to the interface, or NULL in case of failure */ @@ -532,11 +533,9 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) { } virMutexLock(conn-lock); -/* TODO search by MAC first as they are better differentiators */ - ret = (virInterfacePtr) virHashLookup(conn-interfaces, name); -/* TODO check the MAC */ -if (ret == NULL) { + +if ((ret == NULL) || STRCASENEQ(ret-mac, mac)) { if (VIR_ALLOC(ret) 0) { virReportOOMError(conn); goto error; @@ -593,7 +592,6 @@ virReleaseInterface(virInterfacePtr iface) { virConnectPtr conn = iface-conn; DEBUG(release interface %p %s, iface, iface-name); -/* TODO search by MAC first as they are better differenciators */ if (virHashRemoveEntry(conn-interfaces, iface-name, NULL) 0) virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, _(interface missing from connection hash table)); -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 3/4] Add a test interface driver.
--- src/test.c | 392 +++- 1 files changed, 391 insertions(+), 1 deletions(-) diff --git a/src/test.c b/src/test.c index 6f07462..098d235 100644 --- a/src/test.c +++ b/src/test.c @@ -41,6 +41,7 @@ #include capabilities.h #include memory.h #include network_conf.h +#include interface_conf.h #include domain_conf.h #include domain_event.h #include event.h @@ -72,6 +73,7 @@ struct _testConn { virNodeInfo nodeInfo; virDomainObjList domains; virNetworkObjList networks; +virInterfaceObjList ifaces; virStoragePoolObjList pools; int numCells; testCell cells[MAX_CELLS]; @@ -202,6 +204,17 @@ static const char *defaultNetworkXML = /ip /network; +static const char *defaultInterfaceXML = +interface type=\ethernet\ name=\eth1\ + start mode=\onboot\/ + mac address=\aa:bb:cc:dd:ee:ff\/ + mtu size=\1492\/ + protocol family=\ipv4\ +ip address=\192.168.0.5\ prefix=\24\/ +route gateway=\192.168.0.1\/ + /protocol +/interface; + static const char *defaultPoolXML = pool type='dir' namedefault-pool/name @@ -223,6 +236,8 @@ static int testOpenDefault(virConnectPtr conn) { virDomainObjPtr domobj = NULL; virNetworkDefPtr netdef = NULL; virNetworkObjPtr netobj = NULL; +virInterfaceDefPtr interfacedef = NULL; +virInterfaceObjPtr interfaceobj = NULL; virStoragePoolDefPtr pooldef = NULL; virStoragePoolObjPtr poolobj = NULL; @@ -286,6 +301,15 @@ static int testOpenDefault(virConnectPtr conn) { netobj-persistent = 1; virNetworkObjUnlock(netobj); +if (!(interfacedef = virInterfaceDefParseString(conn, defaultInterfaceXML))) +goto error; +if (!(interfaceobj = virInterfaceAssignDef(conn, privconn-ifaces, interfacedef))) { +virInterfaceDefFree(interfacedef); +goto error; +} +interfaceobj-active = 1; +virInterfaceObjUnlock(interfaceobj); + if (!(pooldef = virStoragePoolDefParseString(conn, defaultPoolXML))) goto error; @@ -309,6 +333,7 @@ static int testOpenDefault(virConnectPtr conn) { error: virDomainObjListFree(privconn-domains); virNetworkObjListFree(privconn-networks); +virInterfaceObjListFree(privconn-ifaces); virStoragePoolObjListFree(privconn-pools); virCapabilitiesFree(privconn-caps); testDriverUnlock(privconn); @@ -429,10 +454,11 @@ static int testOpenFromFile(virConnectPtr conn, char *str; xmlDocPtr xml = NULL; xmlNodePtr root = NULL; -xmlNodePtr *domains = NULL, *networks = NULL, *pools = NULL; +xmlNodePtr *domains = NULL, *networks = NULL, *ifaces = NULL, *pools = NULL; xmlXPathContextPtr ctxt = NULL; virNodeInfoPtr nodeInfo; virNetworkObjPtr net; +virInterfaceObjPtr iface; virDomainObjPtr dom; testConnPtr privconn; if (VIR_ALLOC(privconn) 0) { @@ -629,6 +655,39 @@ static int testOpenFromFile(virConnectPtr conn, } VIR_FREE(networks); +/* Parse interface definitions */ +ret = virXPathNodeSet(conn, /node/interface, ctxt, ifaces); +if (ret 0) { +testError(NULL, VIR_ERR_XML_ERROR, %s, _(node interface list)); +goto error; +} +for (i = 0 ; i ret ; i++) { +virInterfaceDefPtr def; +char *relFile = virXMLPropString(ifaces[i], file); +if (relFile != NULL) { +char *absFile = testBuildFilename(file, relFile); +VIR_FREE(relFile); +if (!absFile) { +testError(NULL, VIR_ERR_INTERNAL_ERROR, %s, _(resolving interface filename)); +goto error; +} + +def = virInterfaceDefParseFile(conn, absFile); +VIR_FREE(absFile); +if (!def) +goto error; +} else { +if ((def = virInterfaceDefParseNode(conn, xml, ifaces[i])) == NULL) +goto error; +} +if (!(iface = virInterfaceAssignDef(conn, privconn-ifaces, def))) { +virInterfaceDefFree(def); +goto error; +} +virInterfaceObjUnlock(iface); +} +VIR_FREE(ifaces); + /* Parse Storage Pool list */ ret = virXPathNodeSet(conn, /node/pool, ctxt, pools); if (ret 0) { @@ -692,11 +751,13 @@ static int testOpenFromFile(virConnectPtr conn, xmlFreeDoc(xml); VIR_FREE(domains); VIR_FREE(networks); +VIR_FREE(ifaces); VIR_FREE(pools); if (fd != -1) close(fd); virDomainObjListFree(privconn-domains); virNetworkObjListFree(privconn-networks); +virInterfaceObjListFree(privconn-ifaces); virStoragePoolObjListFree(privconn-pools); testDriverUnlock(privconn); VIR_FREE(privconn); @@ -765,6 +826,7 @@ static int testClose(virConnectPtr conn) virCapabilitiesFree(privconn-caps); virDomainObjListFree(privconn-domains); virNetworkObjListFree(privconn-networks); +virInterfaceObjListFree(privconn-ifaces);
[libvirt] [patch] initialize a local variable in qemudOpenMonitorUnix()
This patch initializes a local variable in qemudOpenMonitorUnix(), thus also eliminates a compilation warning. diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 00dc6e5..d2db1a2 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -874,7 +874,7 @@ qemudOpenMonitorUnix(virConnectPtr conn, struct sockaddr_un addr; int monfd; int timeout = 3; /* In seconds */ -int ret, i; +int ret, i = 0; if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) 0) { virReportSystemError(conn, errno, -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] How to config my VM to use KVM with libvirt?
Hi, I have a VM running under libvirt, and it is currently run with -no-kvm option (I saw that in ps output). Now I want to run this VM with KVM. How can I reconfigure it for that? I looked into its configuration file under /etc/libvirt/qemu, but didnt see any option to turn KVM on. Thanks, J -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] rpm spec cleanup and split off client only requirements
On Mon, Jul 20, 2009 at 05:46:37PM +0100, Daniel P. Berrange wrote: On Mon, Jul 20, 2009 at 06:34:26PM +0200, Daniel Veillard wrote: So I moved in the client: - the shared library, I guess it's uncontroversial - the virsh/virt-xml-validate binaries, I guess it it doesn't block i386/x86_64 to be parallel installable that's fine - the man pages, obvious based on previous - the proxy when built, more controversial, it assumes that there is a service running locally so could be left on the main package Yeah, I think this is best left in the main package. Even in proxy mode, you still really need libvirtd for the networking/storage APIs, so its minimal use to have it in the client. - sasl and policykit data, more controversial, I guess it's better to associate them with the client The SASL config file is needed by both the client server, so it has to go in the -client RPM as you've done. PolicyKit is only used by libvirtd, so its best left in the main package - the schemas to allow checking on the client Makes sense. Okay I commited this and pushed, I first verified there was not trouble having libvirt-client x86_64 and i586 installed in parallel. +%if %{with_sasl} +Requires: cyrus-sasl +# Not technically required, but makes 'out-of-box' config +# work correctly doesn't have onerous dependencies +Requires: cyrus-sasl-md5 +%endif Latest IETF guidlines are moving to deprecate SASL md5 as insufficiently secure, so we should probably just drop this 'cyrus-sasl-md5' altogether, and update our docs default config to be kerberos. Okay, but IMHO this is mostly a documentation issue, once that is fixed, then we can update the package, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] libvirt-java, deprecated methods?
Hi, I'm playing around with libvirt-0.6.5 and libvirt-java-0.2.1 these days. It looks very interesting, but I think I may have found a bug: conn = new Connect(xen://node02, false); conn.setDom0Memory(512000) gives: exception caught:org.libvirt.LibvirtException: invalid domain pointer in virDomainSetMemory level:VIR_ERR_ERROR code:VIR_ERR_INVALID_DOMAIN domain:VIR_FROM_DOM hasConn:false hasDom:false hasNet:false message:invalid domain pointer in virDomainSetMemory str1:invalid domain pointer in %s str2:virDomainSetMemory str3:null int1:0 int2:0 Furthermore, f.e. conn.GetHypervisorVersion(conn.getType()) gives: exception caught:org.libvirt.LibvirtException: this function is not supported by the hypervisor: Xen level:VIR_ERR_ERROR code:VIR_ERR_NO_SUPPORT domain:VIR_FROM_NONE hasConn:false hasDom:false hasNet:false message:this function is not supported by the hypervisor: Xen str1:this function is not supported by the hypervisor: %s str2:Xen str3:null int1:0 int2:0 But Domain dom0=conn.domainLookupByID(0); //domainLookupByName(Domain-0); too DomainInfo dom0info = dom0.getInfo(); dom0.setMemory(256000); works without glitches and does the job (btw, I can't see any effect of setMaxMemory() on Xen?) Is it possible that there are some inconsistences between libvirt-java and libvirt? Since libvirt-java wasn't updated approx. 1y, I assume that. Thanks for feedback, kr, thomas -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [patch] initialize a local variable in qemudOpenMonitorUnix()
On Tue, Jul 21, 2009 at 03:18:21PM +0900, Jun Koi wrote: This patch initializes a local variable in qemudOpenMonitorUnix(), thus also eliminates a compilation warning. Oops, right that's a nasty bug, applied and commited, thanks a lot ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] How to config my VM to use KVM with libvirt?
On Tue, Jul 21, 2009 at 05:47:15PM +0900, Jun Koi wrote: Hi, I have a VM running under libvirt, and it is currently run with -no-kvm option (I saw that in ps output). Now I want to run this VM with KVM. How can I reconfigure it for that? I looked into its configuration file under /etc/libvirt/qemu, but didnt see any option to turn KVM on. Run 'virsh edit GUEST' and on the top domain element, change the type attribute to be 'kvm' instead of 'qemu'. ALso in the emulator element change the path to point to /usr/bin/qemu-kvm NB, make sure you have the kvm modules loaded of course, otherwise it'll still fallback to emulation Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] How to config my VM to use KVM with libvirt?
On Tue, Jul 21, 2009 at 7:14 PM, Daniel P. Berrangeberra...@redhat.com wrote: On Tue, Jul 21, 2009 at 05:47:15PM +0900, Jun Koi wrote: Hi, I have a VM running under libvirt, and it is currently run with -no-kvm option (I saw that in ps output). Now I want to run this VM with KVM. How can I reconfigure it for that? I looked into its configuration file under /etc/libvirt/qemu, but didnt see any option to turn KVM on. Run 'virsh edit GUEST' and on the top domain element, change the type attribute to be 'kvm' instead of 'qemu'. ALso in the emulator element change the path to point to /usr/bin/qemu-kvm exellent, thanks! J -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] MemoryPeek() is slow
Hi, I play around with MemoryPeek() API on QEMU. While it works well, I found that it is too slow. That is expected because of the way it works: we always need to save memory to a file, and read it in again, and that is too inefficient. I am trying to figure out a better way to do this. To do that, clearly we need to re-architecture QEMU for this: We must have another way to read memory from outside the QEMU process. Anybody could suggest a solution for this problem? I am willing to spend time on this feature to improve the situation. Thanks, J -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] MemoryPeek() is slow
On Tue, Jul 21, 2009 at 07:39:07PM +0900, Jun Koi wrote: Hi, I play around with MemoryPeek() API on QEMU. While it works well, I found that it is too slow. Slow in what context ? Are you trying to read large amounts of data out of the guest ? That is expected because of the way it works: we always need to save memory to a file, and read it in again, and that is too inefficient. Possibly, but there's quite a few other variables in the stack that could impact performance too. eg you've got at least 3 more data copies in the libvirt RPC layer ontop of that. Also the libvirt RPC layer and API for memory peek has synchronous round-trips which will result in bad throughput if making lot sof peek calls in a row I am trying to figure out a better way to do this. To do that, clearly we need to re-architecture QEMU for this: We must have another way to read memory from outside the QEMU process. Anybody could suggest a solution for this problem? I am willing to spend time on this feature to improve the situation. Could you explain in more detail what you are using the memory peek API for ? That might suggest a completely different libvirt API, or even something outside of libvirft Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] libvirt-java, deprecated methods?
On Tue, Jul 21, 2009 at 11:52:11AM +0200, Thomas Treutner wrote: Hi, I'm playing around with libvirt-0.6.5 and libvirt-java-0.2.1 these days. It looks very interesting, but I think I may have found a bug: conn = new Connect(xen://node02, false); conn.setDom0Memory(512000) Hmm, dunno what that method is doing - it doesn't correspond to one in the libvirt C API. It would be worth gettinga trace of API calls by setting the following environment variables before running your app LIBVIRT_LOG_FILTERS=1:libvirt LIBVIRT_LOG_OUTPUTS=1:stderr Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/9] Add support for (qcow*) volume encryption
Hello, the following patches add full support for qcow/qcow2 volume encryption, assuming a client that supports it. New XML tags are defined to represent encryption parameters (currently format and passphrase, more can be added in the future), e.g. encryption format='qcow' passphrasec2lsbHk=/passphrase /encryption (passphrase content uses base64) The encryption tag can be added to a volume node passed to virStorageVolCreateXML() to create an encrypted volume, or to a disk node inside a domain to specify what encryption parameters to use for a domain. If the domain is persistent, the parameters (including the passphrase) will be saved unencrypted in /etc/libvirtd; the primary use case is to store the parameters outside of libvirtd, (perhaps by virt-manager in a GNOME keyring). Possible enhancements: - Documentation and test cases. I'll write both if the code is acceptable, I wanted to make the code available for review first. - Support for dumb clients that don't know anything about encryption formats and the required parameters: adding an encryption format to libvirt would automatically make it supported in all clients. Such a client would only request that a volume should be created when creating it, and libvirt would choose an appropriate format, parameters and passphrase/key and return it to the client, who could later pass it unmodified inside a domain. This requires public API additions to let libvirt return the encryption information as one of the results of a volume creation operation. - Support for storing the passphrases/keys used by persistent domains outside of the main XML files, e.g. in a separate passphrase-encrypted file that must be entered on libvirtd startup. -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/9] Add volume encryption information handling.
Define an encryption tag specifying volume encryption format and format-depenedent parameters (e.g. passphrase, cipher name, key length, key). In most cases, the secrets (passphrases/keys) should only be transferred from libvirt users to libvirt, not the other way around. (Volume creation, when libvirt generates secrets for the user, is the only planned exception). Permanent storage of the secrets should be implemented outside of libvirt, although virDomainDefineXML() will cause libvirtd to store the secret locally with a domain. Only the qcow/qcow2 encryption format is currently supported, with the key/passphrase represented using base64. This patch does not add any users; the encryption tag is added in the following patches to both volumes (to support encrypted volume creation) and domains. --- bootstrap|1 + po/POTFILES.in |1 + src/Makefile.am |1 + src/libvirt_private.syms |5 + src/storage_encryption.c | 252 ++ src/storage_encryption.h | 62 +++ 6 files changed, 322 insertions(+), 0 deletions(-) create mode 100644 src/storage_encryption.c create mode 100644 src/storage_encryption.h diff --git a/bootstrap b/bootstrap index 8b81e0e..885b299 100755 --- a/bootstrap +++ b/bootstrap @@ -65,6 +65,7 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool $gnulib_tool || exit modules=' +base64 c-ctype close connect diff --git a/po/POTFILES.in b/po/POTFILES.in index 0ea21fd..cc99b48 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -37,6 +37,7 @@ src/storage_backend_logical.c src/storage_backend_scsi.c src/storage_conf.c src/storage_driver.c +src/storage_encryption.c src/test.c src/uml_conf.c src/uml_driver.c diff --git a/src/Makefile.am b/src/Makefile.am index 9b662ae..6c628bd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,6 +51,7 @@ UTIL_SOURCES = \ memory.c memory.h \ pci.c pci.h \ qparams.c qparams.h \ + storage_encryption.h storage_encryption.c \ threads.c threads.h \ threads-pthread.h \ threads-win32.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 59c78d5..9850daa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -324,6 +324,11 @@ virStoragePartedFsTypeTypeToString; virStoragePoolObjLock; virStoragePoolObjUnlock; +virStorageEncryptionFree; +virStorageEncryptionDropSecrets; +virStorageEncryptionParseNode; +virStorageEncryptionFormat; + # threads.h virMutexInit; diff --git a/src/storage_encryption.c b/src/storage_encryption.c new file mode 100644 index 000..c3e3219 --- /dev/null +++ b/src/storage_encryption.c @@ -0,0 +1,252 @@ +/* + * storage_encryption.h: volume encryption information + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Red Hat Author: Miloslav TrmaÄ m...@redhat.com + */ + +#include config.h + +#include internal.h + +#include base64.h +#include buf.h +#include memory.h +#include storage_conf.h +#include storage_encryption.h +#include util.h +#include xml.h +#include virterror_internal.h + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_ENUM_IMPL(virStorageEncryptionFormat, + VIR_STORAGE_ENCRYPTION_FORMAT_LAST, unencrypted, qcow) + +void +virStorageEncryptionFree(virStorageEncryptionPtr enc) +{ +if (!enc) +return; + +switch (enc-format) { +case VIR_STORAGE_ENCRYPTION_FORMAT_UNENCRYPTED: +break; + +case VIR_STORAGE_ENCRYPTION_FORMAT_QCOW: +if (enc-v.qcow.passphrase != NULL) { +memset(enc-v.qcow.passphrase, 0, + strlen(enc-v.qcow.passphrase)); +VIR_FREE(enc-v.qcow.passphrase); +} +break; + +default: +virStorageReportError(NULL, VIR_ERR_INTERNAL_ERROR, + _(unhandled volume encryption format %d), +
[libvirt] [PATCH 2/9] Attach encryption information to virStorageVolDef.
The XML allows encryption format='unencrypted'/, this implementation canonicalizes the internal representation so that vol-encryption is non-NULL iff the volume is encrypted. Note that partial encryption information (e.g. specifying an encryption format, but not the key/passphrase) is valid: * virStorageVolGetXMLDesc() will never reveal the key/passphrase, even if known by libvirt. * Future mechanisms could be set up to allow a libvirt user to specify during volume creation that a volume should be encrypted, leaving libvirt to choose suitable parameters and key and return them: this would allow the libvirt user to automatically support any encryption parameters (and perhaps encryption formats) supported in libvirt, as long as the user can send the same information back when using the volume in the future. --- src/storage_conf.c | 19 +++ src/storage_conf.h |2 ++ 2 files changed, 21 insertions(+), 0 deletions(-) diff --git a/src/storage_conf.c b/src/storage_conf.c index 075279c..4a77e87 100644 --- a/src/storage_conf.c +++ b/src/storage_conf.c @@ -267,6 +267,7 @@ virStorageVolDefFree(virStorageVolDefPtr def) { VIR_FREE(def-target.perms.label); VIR_FREE(def-backingStore.path); VIR_FREE(def-backingStore.perms.label); +virStorageEncryptionFree(def-encryption); VIR_FREE(def); } @@ -960,6 +961,7 @@ virStorageVolDefParseXML(virConnectPtr conn, char *allocation = NULL; char *capacity = NULL; char *unit = NULL; +xmlNodePtr node; options = virStorageVolOptionsForPoolType(pool-type); if (options == NULL) @@ -1047,6 +1049,19 @@ virStorageVolDefParseXML(virConnectPtr conn, ./backingStore/permissions, 0600) 0) goto cleanup; +node = virXPathNode(conn, ./encryption, ctxt); +if (node != NULL) { +virStorageEncryptionPtr enc; + +enc = virStorageEncryptionParseNode(conn, ctxt-doc, node); +if (enc == NULL) +goto cleanup; +if (enc-format != VIR_STORAGE_ENCRYPTION_FORMAT_UNENCRYPTED) +ret-encryption = enc; +else +virStorageEncryptionFree(enc); +} + return ret; cleanup: @@ -1254,6 +1269,10 @@ virStorageVolDefFormat(virConnectPtr conn, def-backingStore, backingStore) 0) goto cleanup; +if (def-encryption != NULL +virStorageEncryptionFormat(conn, buf, def-encryption, false) 0) +goto cleanup; + virBufferAddLit(buf,/volume\n); if (virBufferError(buf)) diff --git a/src/storage_conf.h b/src/storage_conf.h index a6c3650..cd6944f 100644 --- a/src/storage_conf.h +++ b/src/storage_conf.h @@ -26,6 +26,7 @@ #include internal.h #include util.h +#include storage_encryption.h #include threads.h #include libxml/tree.h @@ -95,6 +96,7 @@ struct _virStorageVolDef { virStorageVolSource source; virStorageVolTarget target; virStorageVolTarget backingStore; +virStorageEncryptionPtr encryption; /* only used if not unencrypted */ }; typedef struct _virStorageVolDefList virStorageVolDefList; -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 3/9] Recognize encryption format of qcow volumes.
(The implementation is not very generic, but that can be very easily rectified if/when new encryption formats appear.) --- src/storage_backend_fs.c | 61 +++-- 1 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c index 8cfc462..0219eb6 100644 --- a/src/storage_backend_fs.c +++ b/src/storage_backend_fs.c @@ -26,6 +26,7 @@ #include sys/statvfs.h #include sys/types.h #include sys/stat.h +#include stdbool.h #include stdio.h #include dirent.h #include errno.h @@ -81,6 +82,9 @@ struct FileTypeInfo { /* Store a COW base image path (possibly relative), * or NULL if there is no COW base image, to RES; * return BACKING_STORE_* */ +int qcowCryptOffset; /* Byte offset from start of file + * where to find encryption mode, + * -1 if encryption is not used */ int (*getBackingStore)(virConnectPtr conn, char **res, const unsigned char *buf, size_t buf_size); }; @@ -89,54 +93,54 @@ struct FileTypeInfo const fileTypeInfo[] = { /* XXX Untested { VIR_STORAGE_VOL_FILE_BOCHS, Bochs Virtual HD Image, NULL, LV_LITTLE_ENDIAN, 64, 0x2, - 32+16+16+4+4+4+4+4, 8, 1, NULL },*/ + 32+16+16+4+4+4+4+4, 8, 1, -1, NULL },*/ /* CLoop */ /* XXX Untested { VIR_STORAGE_VOL_CLOOP, #!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 mount -r -t iso9660 /dev/cloop $1\n, NULL, LV_LITTLE_ENDIAN, -1, 0, - -1, 0, 0, NULL }, */ + -1, 0, 0, -1, NULL }, */ /* Cow */ { VIR_STORAGE_VOL_FILE_COW, OOOM, NULL, LV_BIG_ENDIAN, 4, 2, - 4+4+1024+4, 8, 1, cowGetBackingStore }, + 4+4+1024+4, 8, 1, -1, cowGetBackingStore }, /* DMG */ /* XXX QEMU says there's no magic for dmg, but we should check... */ { VIR_STORAGE_VOL_FILE_DMG, NULL, .dmg, 0, -1, 0, - -1, 0, 0, NULL }, + -1, 0, 0, -1, NULL }, /* XXX there's probably some magic for iso we can validate too... */ { VIR_STORAGE_VOL_FILE_ISO, NULL, .iso, 0, -1, 0, - -1, 0, 0, NULL }, + -1, 0, 0, -1, NULL }, /* Parallels */ /* XXX Untested { VIR_STORAGE_VOL_FILE_PARALLELS, WithoutFreeSpace, NULL, LV_LITTLE_ENDIAN, 16, 2, - 16+4+4+4+4, 4, 512, NULL }, + 16+4+4+4+4, 4, 512, -1, NULL }, */ /* QCow */ { VIR_STORAGE_VOL_FILE_QCOW, QFI, NULL, LV_BIG_ENDIAN, 4, 1, - 4+4+8+4+4, 8, 1, qcowXGetBackingStore }, + 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcowXGetBackingStore }, /* QCow 2 */ { VIR_STORAGE_VOL_FILE_QCOW2, QFI, NULL, LV_BIG_ENDIAN, 4, 2, - 4+4+8+4+4, 8, 1, qcowXGetBackingStore }, + 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcowXGetBackingStore }, /* VMDK 3 */ /* XXX Untested { VIR_STORAGE_VOL_FILE_VMDK, COWD, NULL, LV_LITTLE_ENDIAN, 4, 1, - 4+4+4, 4, 512, NULL }, + 4+4+4, 4, 512, -1, NULL }, */ /* VMDK 4 */ { VIR_STORAGE_VOL_FILE_VMDK, KDMV, NULL, LV_LITTLE_ENDIAN, 4, 1, - 4+4+4, 8, 512, vmdk4GetBackingStore }, + 4+4+4, 8, 512, -1, vmdk4GetBackingStore }, /* Connectix / VirtualPC */ /* XXX Untested { VIR_STORAGE_VOL_FILE_VPC, conectix, NULL, LV_BIG_ENDIAN, -1, 0, - -1, 0, 0, NULL}, + -1, 0, 0, -1, NULL}, */ }; @@ -282,13 +286,16 @@ static int virStorageBackendProbeTarget(virConnectPtr conn, virStorageVolTargetPtr target, char **backingStore, unsigned long long *allocation, -unsigned long long *capacity) { +unsigned long long *capacity, +virStorageEncryptionPtr *encryption) { int fd; unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */ int len, i, ret; if (backingStore) *backingStore = NULL; +if (encryption) +*encryption = NULL; if ((fd = open(target-path, O_RDONLY)) 0) { virReportSystemError(conn, errno, @@ -317,6 +324,8 @@ static int virStorageBackendProbeTarget(virConnectPtr conn, /* First check file magic */ for (i = 0 ; i ARRAY_CARDINALITY(fileTypeInfo) ; i++) { int mlen; +bool encrypted_qcow = false; + if (fileTypeInfo[i].magic == NULL) continue; @@ -375,6 +384,16 @@ static int virStorageBackendProbeTarget(virConnectPtr conn, *capacity *= fileTypeInfo[i].sizeMultiplier; } +if (fileTypeInfo[i].qcowCryptOffset != -1) { +int crypt_format; + +crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] 24) | +(head[fileTypeInfo[i].qcowCryptOffset+1] 16) | +
[libvirt] [PATCH 4/9] Add support for encrypted (qcow) volume creation.
Supports only virStorageVolCreateXML, not virStorageVolCreateXMLFrom. Curiously, qemu-img does not need the passphrase for anything to create an encrypted volume. This implementation is sufficient for the qcow2 format, and for other formats when all encryption parameters are pre-specified. The qcow2 passphrase is stored in libvirt only during the volume creation operation, and automatically deleted afterwards. Other users might be able to query the volume properties while the volume is being created, but virStorageVolGetXMLDesc() won't reveal the passphrase to them. An earlier patch description has mentioned the possibility of a libvirt user specifying only the encryption format (or not even the format), letting libvirt to choose the parameters and return them. This would require libvirt interface extensions, and it is not supported by this patch. --- src/storage_backend.c | 41 +++-- src/storage_backend_disk.c|7 +++ src/storage_backend_fs.c |7 +++ src/storage_backend_logical.c |7 +++ src/storage_driver.c |4 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/storage_backend.c b/src/storage_backend.c index 1664804..42c59ad 100644 --- a/src/storage_backend.c +++ b/src/storage_backend.c @@ -246,6 +246,13 @@ virStorageBackendCreateRaw(virConnectPtr conn, unsigned long long remain; char *buf = NULL; +if (vol-encryption != NULL) { +virStorageReportError(conn, VIR_ERR_NO_SUPPORT, + %s, _(storage pool does not support encrypted + volumes)); +return -1; +} + if ((fd = open(vol-target.path, O_RDWR | O_CREAT | O_EXCL, vol-target.perms.mode)) 0) { virReportSystemError(conn, errno, @@ -346,15 +353,17 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, NULL; const char **imgargv; +/* The extra NULL field is for indicating encryption (-e). */ const char *imgargvnormal[] = { NULL, create, -f, type, vol-target.path, size, NULL, +NULL }; /* Extra NULL fields are for including backingType when using - * kvm-img. It's -F backingType + * kvm-img (-F backingType), and for indicating encryption (-e). */ const char *imgargvbacking[] = { NULL, create, @@ -364,6 +373,7 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, size, NULL, NULL, +NULL, NULL }; const char *convargv[] = { @@ -417,6 +427,22 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, } } +if (vol-encryption != NULL) { +if (vol-encryption-format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW) { +virStorageReportError(conn, VIR_ERR_NO_SUPPORT, + _(unsupported volume encryption format %d), + vol-encryption-format); +return -1; +} +if (vol-target.format != VIR_STORAGE_VOL_FILE_QCOW +vol-target.format != VIR_STORAGE_VOL_FILE_QCOW2) { +virStorageReportError(conn, VIR_ERR_NO_SUPPORT, + _(qcow volume encryption unsupported with +volume format %s), type); +return -1; +} +} + if ((create_tool = virFindFileInPath(kvm-img)) != NULL) use_kvmimg = 1; else if ((create_tool = virFindFileInPath(qemu-img)) != NULL) @@ -437,11 +463,16 @@ virStorageBackendCreateQemuImg(virConnectPtr conn, imgargvbacking[7] = backingType; imgargvbacking[8] = vol-target.path; imgargvbacking[9] = size; -} +if (vol-encryption != NULL) +imgargvbacking[10] = -e; +} else if (vol-encryption != NULL) +imgargvbacking[8] = -e; imgargv = imgargvbacking; } else { imgargvnormal[0] = create_tool; imgargv = imgargvnormal; +if (vol-encryption != NULL) +imgargv[6] = -e; } @@ -490,6 +521,12 @@ virStorageBackendCreateQcowCreate(virConnectPtr conn, qcow-create)); return -1; } +if (vol-encryption != NULL) { +virStorageReportError(conn, VIR_ERR_NO_SUPPORT, + %s, _(encrypted volumes not supported with + qcow-create)); +return -1; +} /* Size in MB - yes different units to qemu-img :-( */ snprintf(size, sizeof(size), %llu, vol-capacity/1024/1024); diff --git a/src/storage_backend_disk.c b/src/storage_backend_disk.c index ae2acae..8f4f0ed 100644 --- a/src/storage_backend_disk.c +++ b/src/storage_backend_disk.c @@ -557,6 +557,13 @@ virStorageBackendDiskCreateVol(virConnectPtr conn, NULL }; +if
[libvirt] [PATCH 5/9] Attach encryption information to virDomainDiskDef.
The XML allows encryption format='unencrypted'/, this implementation canonicalizes the internal representation so that disk-encryption is non-NULL iff encryption information is available. Note that partial encryption information (e.g. specifying an encryption format, but not the key/passphrase) is valid: * virDomainGetXMLDesc() will only reveal the key/passphrase if VIR_DOMAIN_XML_SECURE is used. * A domain with partial encryption information can be defined, completenes of the information is not verified. The domain won't start until the remaining information is added, of course. --- src/domain_conf.c | 25 +++-- src/domain_conf.h |2 ++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/domain_conf.c b/src/domain_conf.c index f3e4c6c..507abd8 100644 --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -287,6 +287,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def) VIR_FREE(def-dst); VIR_FREE(def-driverName); VIR_FREE(def-driverType); +virStorageEncryptionFree(def-encryption); VIR_FREE(def); } @@ -654,6 +655,7 @@ virDomainDiskDefParseXML(virConnectPtr conn, char *target = NULL; char *bus = NULL; char *cachetag = NULL; +virStorageEncryptionPtr encryption = NULL; if (VIR_ALLOC(def) 0) { virReportOOMError(conn); @@ -708,6 +710,17 @@ virDomainDiskDefParseXML(virConnectPtr conn, def-readonly = 1; } else if (xmlStrEqual(cur-name, BAD_CAST shareable)) { def-shared = 1; +} else if (encryption == NULL + xmlStrEqual(cur-name, BAD_CAST encryption)) { +encryption = virStorageEncryptionParseNode(conn, node-doc, + cur); +if (encryption == NULL) +goto error; +if (encryption-format == +VIR_STORAGE_ENCRYPTION_FORMAT_UNENCRYPTED) { +virStorageEncryptionFree(encryption); +encryption = NULL; +} } } cur = cur-next; @@ -815,6 +828,8 @@ virDomainDiskDefParseXML(virConnectPtr conn, driverName = NULL; def-driverType = driverType; driverType = NULL; +def-encryption = encryption; +encryption = NULL; cleanup: VIR_FREE(bus); @@ -825,6 +840,7 @@ cleanup: VIR_FREE(driverType); VIR_FREE(driverName); VIR_FREE(cachetag); +virStorageEncryptionFree(encryption); return def; @@ -3387,7 +3403,8 @@ virDomainLifecycleDefFormat(virConnectPtr conn, static int virDomainDiskDefFormat(virConnectPtr conn, virBufferPtr buf, - virDomainDiskDefPtr def) + virDomainDiskDefPtr def, + int flags) { const char *type = virDomainDiskTypeToString(def-type); const char *device = virDomainDiskDeviceTypeToString(def-device); @@ -3444,6 +3461,10 @@ virDomainDiskDefFormat(virConnectPtr conn, virBufferAddLit(buf, readonly/\n); if (def-shared) virBufferAddLit(buf, shareable/\n); +if (def-encryption != NULL +virStorageEncryptionFormat(conn, buf, def-encryption, + (flags VIR_DOMAIN_XML_SECURE)) 0) +return -1; virBufferAddLit(buf, /disk\n); @@ -4047,7 +4068,7 @@ char *virDomainDefFormat(virConnectPtr conn, def-emulator); for (n = 0 ; n def-ndisks ; n++) -if (virDomainDiskDefFormat(conn, buf, def-disks[n]) 0) +if (virDomainDiskDefFormat(conn, buf, def-disks[n], flags) 0) goto cleanup; for (n = 0 ; n def-nfss ; n++) diff --git a/src/domain_conf.h b/src/domain_conf.h index 6e111fa..32d03ac 100644 --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -30,6 +30,7 @@ #include internal.h #include capabilities.h +#include storage_encryption.h #include util.h #include threads.h @@ -107,6 +108,7 @@ struct _virDomainDiskDef { unsigned int readonly : 1; unsigned int shared : 1; int slotnum; /* pci slot number for unattach */ +virStorageEncryptionPtr encryption; }; -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 6/9] Don't assume buffered output echoes the command.
The if ((nlptr...)) implicitly assumes commptr != NULL. Make the assumption explicit, it will be broken in a future patch. --- src/qemu_driver.c |7 --- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qemu_driver.c b/src/qemu_driver.c index d2db1a2..f2be27f 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -2081,10 +2081,11 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm, * occurence, and inbetween the command and the newline starting * the response */ -if ((commptr = strstr(buf, cmd))) +if ((commptr = strstr(buf, cmd))) { memmove(buf, commptr, strlen(commptr)+1); -if ((nlptr = strchr(buf, '\n'))) -memmove(buf+strlen(cmd), nlptr, strlen(nlptr)+1); +if ((nlptr = strchr(buf, '\n'))) +memmove(buf+strlen(cmd), nlptr, strlen(nlptr)+1); +} break; } -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 7/9] Make handling of monitor prompts more general.
--- src/qemu_driver.c | 87 1 files changed, 73 insertions(+), 14 deletions(-) diff --git a/src/qemu_driver.c b/src/qemu_driver.c index f2be27f..12079f8 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -87,6 +87,12 @@ static void qemuDriverUnlock(struct qemud_driver *driver) virMutexUnlock(driver-lock); } +/* Return -1 for error, 0 for success */ +typedef int qemudMonitorExtraPromptHandler(const virDomainObjPtr vm, + const char *buf, + const char *prompt, + void *data); + static void qemuDomainEventFlush(int timer, void *opaque); static void qemuDomainEventQueue(struct qemud_driver *driver, virDomainEventPtr event); @@ -111,6 +117,12 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom); static int qemudMonitorCommand(const virDomainObjPtr vm, const char *cmd, char **reply); +static int qemudMonitorCommandWithHandler(const virDomainObjPtr vm, + const char *cmd, + const char *extraPrompt, + qemudMonitorExtraPromptHandler extraHandler, + void *handlerData, + char **reply); static int qemudMonitorCommandExtra(const virDomainObjPtr vm, const char *cmd, const char *extra, @@ -2014,15 +2026,15 @@ qemuMonitorDiscardPendingData(virDomainObjPtr vm) { static int -qemudMonitorCommandExtra(const virDomainObjPtr vm, - const char *cmd, - const char *extra, - const char *extraPrompt, - char **reply) { +qemudMonitorCommandWithHandler(const virDomainObjPtr vm, + const char *cmd, + const char *extraPrompt, + qemudMonitorExtraPromptHandler extraHandler, + void *handlerData, + char **reply) { int size = 0; char *buf = NULL; size_t cmdlen = strlen(cmd); -size_t extralen = extra ? strlen(extra) : 0; qemuMonitorDiscardPendingData(vm); @@ -2061,14 +2073,20 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm, /* Look for QEMU prompt to indicate completion */ if (buf) { -if (extra) { -if (strstr(buf, extraPrompt) != NULL) { -if (safewrite(vm-monitor, extra, extralen) != extralen) -return -1; -if (safewrite(vm-monitor, \r, 1) != 1) -return -1; -extra = NULL; -} +char *foundPrompt; + +if (extraPrompt +(foundPrompt = strstr(buf, extraPrompt)) != NULL) { +char *promptEnd; + +if (extraHandler(vm, buf, foundPrompt, handlerData) 0) +return -1; +/* Discard output so far, necessary to detect whether + extraPrompt appears again. We don't need the output between + original command and this prompt anyway. */ +promptEnd = foundPrompt + strlen(extraPrompt); +memmove(buf, promptEnd, strlen(promptEnd)+1); +size -= promptEnd - buf; } else if ((tmp = strstr(buf, QEMU_CMD_PROMPT)) != NULL) { char *commptr = NULL, *nlptr = NULL; /* Preserve the newline */ @@ -2106,6 +2124,47 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm, return -1; } +struct extraHandlerData +{ +const char *reply; +bool first; +}; + +static int +qemudMonitorCommandSimpleExtraHandler(const virDomainObjPtr vm, + const char *buf ATTRIBUTE_UNUSED, + const char *prompt ATTRIBUTE_UNUSED, + void *data_) +{ +struct extraHandlerData *data = data_; +size_t len; + +if (!data-first) +return 0; +len = strlen(data-reply); +if (safewrite(vm-monitor, data-reply, len) != len) +return -1; +if (safewrite(vm-monitor, \r, 1) != 1) +return -1; +data-first = false; +return 0; +} + +static int +qemudMonitorCommandExtra(const virDomainObjPtr vm, + const char *cmd, + const char *extra, + const char *extraPrompt, + char **reply) { +struct extraHandlerData data; + +data.reply = extra; +data.first = true; +return qemudMonitorCommandWithHandler(vm, cmd,
Re: [libvirt] [PATCH 0/4] Updated patches 2-6 - virInterface test driver and netcf backend
On Tue, Jul 21, 2009 at 02:09:38AM -0400, Laine Stump wrote: These patches correspond to patches 2-6 in the set I sent yesterday (the 1st and 2nd had no changes, so they stand as-is). They incorporate all changes brought up in review of the first set. In particular: 1) When looking for a cached virInterface object for an interface, I now check that the mac address being searched for matches the one in the virInterface (case insensitive comparison). If it doesn't match, I create a new object rather than trying to modify the existing object with the same interface name, as that could have led to improper behavior. 2) in virInterfaceFindByMACString() I now follow danpb's suggestion and use continue, rather than getting fancy with booleans. 3) testinterfaceCreate() and testInterfaceDestroy() now check if the interface has already been created/destroyed, and won't do the same operation twice in a row. 4) in the netcf backend driver, I now roundtrip the xml data in both interfaceDefineXML() and interfaceGetXMLDesc(). ACK this series looks good now Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Extra filesystem options during backend filesystem mount.
Hi Daniel, Are you going to apply this to mainline?. Was just wondering if you have any other concerns so that i could work on those if at all there are other better ways you would have. Thanks -- Harshavardhana Gluster - http://www.gluster.com/ On Sat, Jul 18, 2009 at 9:12 AM, Harshavardhana har...@gluster.com wrote: Daniel, Thanks for the pointers, i will keep this mind as and when the problem is fixed i will send a patch against those specific changes. Regards -- Harshavardhana Z Research Inc http://www.zresearch.com/ On Fri, Jul 17, 2009 at 11:58 PM, Daniel P. Berrange berra...@redhat.comwrote: On Thu, Jul 16, 2009 at 08:24:09PM +0530, Harshavardhana wrote: Hi Daniel, On Thu, Jul 16, 2009 at 7:46 PM, Daniel P. Berrange berra...@redhat.comwrote: On Thu, Jul 16, 2009 at 06:06:25AM -0700, Harshavardhana wrote: New option index added to support -o options for various netfs. Currently added an option for glusterfs. What effect does it have ? Or why do we want/need it Options could be required for filesystem to have few enhaced handling at the site where they will be under use. Correct approach for a configurable will be a new XML option in this case. Regarding current patch: This is required for the glusterfs to work properly with VM's. Right now there is a problem/difficulty in using direct-io based mechanism in the fuse kernel module when used with XEN in its tap:aio framework, we have seen xen vms hang over glusterfs or any fuse based filesystem due to fact that fuse module doesn't yet support aio with O_DIRECT internally as a kernel module. To have a work around fix we have to hardcode this value due to its usage in case of VM's. We are currently fixing this problem by fixing directly O_DIRECT problem in fuse. Which will be available in later releases for kernel. ACK, I see why you need this for the current releases of kernel/glusterfs. As when this problem is fixed we'll need to either remove this, or provide a way to turn it off again. I don't think this is the kind of tunable that should be exposed in the XML, since this is really just a hack to work around a bug in a specific releases. Someone using libvirt has no way to decide whether the hack is needed or not, so making them set it in the XML would not be desirable. One possibility would be to have a config file /etc/libvirt/storage.conf for controlling certain options like this per host. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ http://search.cpan.org/%7Edanberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] How to config my VM to use KVM with libvirt?
Daniel P. Berrange wrote: On Tue, Jul 21, 2009 at 05:47:15PM +0900, Jun Koi wrote: Hi, I have a VM running under libvirt, and it is currently run with -no-kvm option (I saw that in ps output). Now I want to run this VM with KVM. How can I reconfigure it for that? I looked into its configuration file under /etc/libvirt/qemu, but didnt see any option to turn KVM on. Run 'virsh edit GUEST' and on the top domain element, change the type attribute to be 'kvm' instead of 'qemu'. Speaking of this, I've noticed that domain type='qemu' os type arch='i686' machine='pc'hvm/type /os /domain runs WITH kvm on an x86_64 system. Is that intended? It seems that this comment in qemu_conf.c: /* Need to explicitly disable KVM if * 1. Arch matches host arch * 2. Guest domain is 'qemu' * 3. The qemu binary has the -no-kvm flag */ might need to expand #1 to consider i686 == x86_64? -jim -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] How to config my VM to use KVM with libvirt?
On Tue, Jul 21, 2009 at 09:46:17AM -0400, Jim Paris wrote: Daniel P. Berrange wrote: On Tue, Jul 21, 2009 at 05:47:15PM +0900, Jun Koi wrote: Hi, I have a VM running under libvirt, and it is currently run with -no-kvm option (I saw that in ps output). Now I want to run this VM with KVM. How can I reconfigure it for that? I looked into its configuration file under /etc/libvirt/qemu, but didnt see any option to turn KVM on. Run 'virsh edit GUEST' and on the top domain element, change the type attribute to be 'kvm' instead of 'qemu'. Speaking of this, I've noticed that domain type='qemu' os type arch='i686' machine='pc'hvm/type /os /domain runs WITH kvm on an x86_64 system. Is that intended? No, its not intended ! It seems that this comment in qemu_conf.c: /* Need to explicitly disable KVM if * 1. Arch matches host arch * 2. Guest domain is 'qemu' * 3. The qemu binary has the -no-kvm flag */ might need to expand #1 to consider i686 == x86_64? I'm actually wondering why we bother with #1 at all. If the binary has '-no-kvm' and the domain is 'qemu', then it should be used no matter what arch. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] libvirt-java, deprecated methods?
On Tue, Jul 21, 2009 at 01:39:51PM +0200, Thomas Treutner wrote: On Tuesday 21 July 2009 13:01:06 Daniel P. Berrange wrote: On Tue, Jul 21, 2009 at 11:52:11AM +0200, Thomas Treutner wrote: Hi, I'm playing around with libvirt-0.6.5 and libvirt-java-0.2.1 these days. It looks very interesting, but I think I may have found a bug: conn = new Connect(xen://node02, false); conn.setDom0Memory(512000) Hmm, dunno what that method is doing - it doesn't correspond to one in the libvirt C API. It would be worth gettinga trace of API calls by setting the following environment variables before running your app LIBVIRT_LOG_FILTERS=1:libvirt LIBVIRT_LOG_OUTPUTS=1:stderr Seems like the domain ID is not defined - not surprisingly: 13:24:07.905: debug : virDomainSetMemory:2601 : domain=(nil), memory=512000 13:24:07.905: error : virLibDomainError:433 : invalid domain pointer in virDomainSetMemory Since the dom0 is AFAIK very xen-specific, I wonder if such a function may ever have been part of libvirt? I've just looked at the java code and found this horrible snippet JNIEXPORT jint JNICALL Java_org_libvirt_Connect__1setDom0Memory (JNIEnv *env, jobject obj, jlong memory){ return virDomainSetMemory(NULL, memory); } This could not possibly have ever worked. It is forbidden to pass NULL to virDomainSetMemory(), no matter what hypervisor driver. We should just remove the setDom0Memory() method from the java code, since it is fundamentally broken always has been Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/4] Updated patches 2-6 - virInterface test driver and netcf backend
On Tue, Jul 21, 2009 at 02:09:38AM -0400, Laine Stump wrote: These patches correspond to patches 2-6 in the set I sent yesterday (the 1st and 2nd had no changes, so they stand as-is). They incorporate all changes brought up in review of the first set. In particular: 1) When looking for a cached virInterface object for an interface, I now check that the mac address being searched for matches the one in the virInterface (case insensitive comparison). If it doesn't match, I create a new object rather than trying to modify the existing object with the same interface name, as that could have led to improper behavior. 2) in virInterfaceFindByMACString() I now follow danpb's suggestion and use continue, rather than getting fancy with booleans. 3) testinterfaceCreate() and testInterfaceDestroy() now check if the interface has already been created/destroyed, and won't do the same operation twice in a row. 4) in the netcf backend driver, I now roundtrip the xml data in both interfaceDefineXML() and interfaceGetXMLDesc(). Okay I have applied everything, congrats ! I hope I didn't forgot anything ... I also applied my old patch to extend .syms, and had to cleanup a couple of things like superflous lines at end of module. One thing we we may have to revisit is how netcf NETCF_ENOMEM is handled, currently we just convert it to VIR_ERR_NO_MEMORY (which gave some syntax-check fun), but we should raise a proper virReportOOMError() instead, code around src/interface_driver.c line 72 may need some tweaking. But with the test driver commited in make check now works properly :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Bugfix for failing to reconnect to vbox:///session
On Mon, Jul 20, 2009 at 10:04:31AM +0200, Pritesh Kothari wrote: I don't think this is quite correct. We call VBoxCGlueInit() in the vboxRegister() function, which is run when libvirt first initializes the whole library. The real bug is the vboxClose() method which calls vboxUninitialize() which is then calling VBoxCGlueTerm(). So if you have many virConectPtr objects open, the first one you call virConnectClose on will shutdown the entire vbox library, breaking all the other virConnectPtr instances you have active. IMHO, we should simply delete VBoxCGlueTerm() completely. Right the VBoxCGlueTerm() is causing the whole problem. Resending the patch with changes as suggested above. Okay, pushed, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] Workaround to start xen inside a buggy kvm
Buggy kvm crashes with kernel panic if xen started inside a kvm machine. kvm needs the -no-kvm-pit, this argument is not available with libvirt. I have tested the following workaround on ubuntu 9.04 Rename kvm cd /usr/bin mv kvm kvm.orig Use the following script instead the original kvm #!/bin/sh exec kvm.orig -no-kvm-pit $* Do not forget chmod +x kvm Have fun, Thomas -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Canonicalize qemu machine types
In qemu-0.11 there is a 'pc-0.10' machine type which allows you to run guests with a machine which is compatible with the pc machine in qemu-0.10 - e.g. using the original PCI class for virtio-blk and virtio-console and disabling MSI support in virtio-net. The idea here is that we don't want to surprise guests by changing the hardware when qemu is updated. I've just posted some patches for qemu-0.11 which allows libvirt to canonicalize the 'pc' machine alias to the latest machine version. This patches makes us use that so that when a guest is configured to use the 'pc' machine type, we resolve that to 'pc-0.11' machine and save that in the guest XML. See also: https://fedoraproject.org/wiki/Features/KVM_Stable_Guest_ABI * src/qemu_conf.c: add qemudCanonicalizeMachine() to parse the output of 'qemu -M ?' * src/qemu_driver.c: canonicalize the machine type in qemudDomainDefine() --- src/qemu_conf.c | 114 + src/qemu_conf.h |3 + src/qemu_driver.c |3 + 3 files changed, 120 insertions(+), 0 deletions(-) diff --git a/src/qemu_conf.c b/src/qemu_conf.c index 4043d70..3f4edfa 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -470,6 +470,120 @@ virCapsPtr qemudCapsInit(void) { return NULL; } +/* Format is: + * machine desc [(alias of machine)] + */ +static int +qemudParseMachineTypesStr(const char *machines ATTRIBUTE_UNUSED, + const char *machine ATTRIBUTE_UNUSED, + char **canonical) +{ +const char *p = machines; + +*canonical = NULL; + +do { +const char *eol; +char *s; + +if (!(eol = strchr(p, '\n'))) +return -1; /* eof file without finding @machine */ + +if (!STRPREFIX(p, machine)) { +p = eol + 1; +continue; /* doesn't match @machine */ +} + +p += strlen(machine); + +if (*p != ' ') { +p = eol + 1; +continue; /* not a complete match of @machine */ +} + +do { +p++; +} while (*p == ' '); + +p = strstr(p, (alias of ); +if (!p || p eol) +return 0; /* not an alias, name is canonical */ + +*canonical = strndup(p + strlen((alias of ), eol - p); + +s = strchr(*canonical, ')'); +if (!s) { +VIR_FREE(*canonical); +*canonical = NULL; +return -1; /* output is screwed up */ +} + +*s = '\0'; +break; +} while (1); + +return 0; +} + +int +qemudCanonicalizeMachine(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainDefPtr def) +{ +const char *const qemuarg[] = { def-emulator, -M, ?, NULL }; +const char *const qemuenv[] = { LC_ALL=C, NULL }; +char *machines, *canonical; +enum { MAX_MACHINES_OUTPUT_SIZE = 1024*4 }; +pid_t child; +int newstdout = -1, len; +int ret = -1, status; + +if (virExec(NULL, qemuarg, qemuenv, NULL, +child, -1, newstdout, NULL, VIR_EXEC_CLEAR_CAPS) 0) +return -1; + +len = virFileReadLimFD(newstdout, MAX_MACHINES_OUTPUT_SIZE, machines); +if (len 0) { +virReportSystemError(NULL, errno, %s, + _(Unable to read 'qemu -M ?' output)); +goto cleanup; +} + +if (qemudParseMachineTypesStr(machines, def-os.machine, canonical) 0) +goto cleanup2; + +if (canonical) { +VIR_FREE(def-os.machine); +def-os.machine = canonical; +} + +ret = 0; + +cleanup2: +VIR_FREE(machines); +cleanup: +if (close(newstdout) 0) +ret = -1; + +rewait: +if (waitpid(child, status, 0) != child) { +if (errno == EINTR) +goto rewait; + +VIR_ERROR(_(Unexpected exit status from qemu %d pid %lu), + WEXITSTATUS(status), (unsigned long)child); +ret = -1; +} +/* Check log unexpected exit status, but don't fail, + * as there's really no need to throw an error if we did + * actually read a valid version number above */ +if (WEXITSTATUS(status) != 0) { +VIR_WARN(_(Unexpected exit status '%d', qemu probably failed), + WEXITSTATUS(status)); +} + +return ret; +} + static unsigned int qemudComputeCmdFlags(const char *help, unsigned int version, unsigned int is_kvm, diff --git a/src/qemu_conf.h b/src/qemu_conf.h index fbf2ab9..b668669 100644 --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -123,6 +123,9 @@ int qemudExtractVersionInfo (const char *qemu, unsigned int *version, unsigned int *flags); +int qemudCanonicalizeMachine(virConnectPtr conn, + virDomainDefPtr def); + int qemudParseHelpStr (const char *str,
Re: [libvirt] libvirt-java, deprecated methods?
On Tue, Jul 21, 2009 at 03:03:53PM +0100, Daniel P. Berrange wrote: On Tue, Jul 21, 2009 at 01:39:51PM +0200, Thomas Treutner wrote: On Tuesday 21 July 2009 13:01:06 Daniel P. Berrange wrote: On Tue, Jul 21, 2009 at 11:52:11AM +0200, Thomas Treutner wrote: Hi, I'm playing around with libvirt-0.6.5 and libvirt-java-0.2.1 these days. You mean libvirt-java-0.1.1, I don't think I ever released a newer version. Unfortunately as you found out the bindings are in a not so nice shape. The good point is that someone with more Java knowledge than me is looking at cleaning this up ! I've just looked at the java code and found this horrible snippet JNIEXPORT jint JNICALL Java_org_libvirt_Connect__1setDom0Memory (JNIEnv *env, jobject obj, jlong memory){ return virDomainSetMemory(NULL, memory); } This could not possibly have ever worked. It is forbidden to pass NULL to virDomainSetMemory(), no matter what hypervisor driver. We should just remove the setDom0Memory() method from the java code, since it is fundamentally broken always has been I never realized we had this in, yup I need to clean this up ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] MemoryPeek() is slow
On Tue, Jul 21, 2009 at 7:50 PM, Daniel P. Berrangeberra...@redhat.com wrote: On Tue, Jul 21, 2009 at 07:39:07PM +0900, Jun Koi wrote: Hi, I play around with MemoryPeek() API on QEMU. While it works well, I found that it is too slow. Slow in what context ? Are you trying to read large amounts of data out of the guest ? Yes. That is expected because of the way it works: we always need to save memory to a file, and read it in again, and that is too inefficient. Possibly, but there's quite a few other variables in the stack that could impact performance too. eg you've got at least 3 more data copies in the libvirt RPC layer ontop of that. Also the libvirt RPC layer and API for memory peek has synchronous round-trips which will result in bad throughput if making lot sof peek calls in a row I am trying to figure out a better way to do this. To do that, clearly we need to re-architecture QEMU for this: We must have another way to read memory from outside the QEMU process. Anybody could suggest a solution for this problem? I am willing to spend time on this feature to improve the situation. Could you explain in more detail what you are using the memory peek API for ? That might suggest a completely different libvirt API, or even something outside of libvirft That is nothing special. I am working on something like virt-top, which requires to read VM's memory. I am also doing some experiments, which requires to get data out as fast as possible. Really I dont think that current multiple layers are the culprit of the slow problem. It must be the way we are reading memory out, as I wrote above. That is way to inefficient, and nobody can deny that. Thanks, J -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Extra filesystem options during backend filesystem mount.
On Tue, Jul 21, 2009 at 06:43:10PM +0530, Harshavardhana wrote: Hi Daniel, Are you going to apply this to mainline?. Was just wondering if you have any other concerns so that i could work on those if at all there are other better ways you would have. Ah right I nearly forgot about it :-) it's commited, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] cp error in api doc
I think there's a cp error: http://libvirt.org/html/libvirt-libvirt.html#virStoragePoolUndefine Returns: a virStoragePoolPtr object, or NULL if creation failed I assume it is 0 on success, -1 on failure as the return is of type int. kr,t -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Add getfd and closefd monitor commands
Add monitor commands to support passing file descriptors via SCM_RIGHTS. getfd assigns the passed file descriptor a name for use with other monitor commands. closefd allows passed file descriptors to be closed. If a monitor command actually uses a named file descriptor, closefd will not be required. Signed-off-by: Mark McLoughlin mar...@redhat.com --- monitor.c | 69 +++ qemu-monitor.hx | 18 ++ 2 files changed, 87 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index e38c86e..817e4b7 100644 --- a/monitor.c +++ b/monitor.c @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { const char *help; } mon_cmd_t; +/* file descriptors passed via SCM_RIGHTS */ +typedef struct mon_fd_t mon_fd_t; +struct mon_fd_t { +char *name; +int fd; +LIST_ENTRY(mon_fd_t) next; +}; + struct Monitor { CharDriverState *chr; int flags; @@ -80,6 +88,7 @@ struct Monitor { CPUState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; +LIST_HEAD(,mon_fd_t) fds; LIST_ENTRY(Monitor) entry; }; @@ -1705,6 +1714,66 @@ static void do_inject_mce(Monitor *mon, } #endif +static void do_getfd(Monitor *mon, const char *fdname) +{ +mon_fd_t *monfd; +int fd; + +fd = qemu_chr_get_msgfd(mon-chr); +if (fd == -1) { +monitor_printf(mon, getfd: no file descriptor supplied via SCM_RIGHTS\n); +return; +} + +if (qemu_isdigit(fdname[0])) { +monitor_printf(mon, getfd: monitor names may not begin with a number\n); +return; +} + +fd = dup(fd); +if (fd == -1) { +monitor_printf(mon, Failed to dup() file descriptor: %s\n, + strerror(errno)); +return; +} + +LIST_FOREACH(monfd, mon-fds, next) { +if (strcmp(monfd-name, fdname) != 0) { +continue; +} + +close(monfd-fd); +monfd-fd = fd; +return; +} + +monfd = qemu_mallocz(sizeof(mon_fd_t)); +monfd-name = qemu_strdup(fdname); +monfd-fd = fd; + +LIST_INSERT_HEAD(mon-fds, monfd, next); +} + +static void do_closefd(Monitor *mon, const char *fdname) +{ +mon_fd_t *monfd; + +LIST_FOREACH(monfd, mon-fds, next) { +if (strcmp(monfd-name, fdname) != 0) { +continue; +} + +LIST_REMOVE(monfd, next); +close(monfd-fd); +qemu_free(monfd-name); +qemu_free(monfd); +return; +} + +monitor_printf(mon, Failed to find file descriptor named %s\n, + fdname); +} + static const mon_cmd_t mon_cmds[] = { #include qemu-monitor.h { NULL, NULL, }, diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 70e2475..11bdb2c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -628,6 +628,24 @@ STEXI Inject an MCE on the given CPU (x86 only). ETEXI +{ getfd, s, do_getfd, getfd name, + receive a file descriptor via SCM rights and assign it a name }, +STEXI +...@item getfd @var{fdname} +If a file descriptor is passed alongside this command using the SCM_RIGHTS +mechanism on unix sockets, it is stored using the name @var{fdname} for +later use by other monitor commands. +ETEXI + +{ closefd, s, do_closefd, closefd name, + close a file descriptor previously passed via SCM rights }, +STEXI +...@item closefd @var{fdname} +Close the file descriptor previously assigned to @var{fdname} using the +...@code{getfd} command. This is only needed if the file descriptor was never +used by another monitor command. +ETEXI + STEXI @end table ETEXI -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Add SCM_RIGHTS support to unix socket character devices
If a file descriptor is passed via a message with SCM_RIGHTS ancillary data on a unix socket, store the file descriptor for use in the chr_read() handler. Close the file descriptor if it was not used. The qemu_chr_get_msgfd() API provides access to the passed descriptor. Signed-off-by: Mark McLoughlin mar...@redhat.com --- qemu-char.c | 50 ++ qemu-char.h |2 ++ 2 files changed, 52 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index e0d7220..f06a614 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) s-chr_read(s-handler_opaque, buf, len); } +int qemu_chr_get_msgfd(CharDriverState *s) +{ +return s-get_msgfd ? s-get_msgfd(s) : -1; +} + void qemu_chr_accept_input(CharDriverState *s) { if (s-chr_accept_input) @@ -1832,6 +1837,7 @@ typedef struct { int do_telnetopt; int do_nodelay; int is_unix; +int msgfd; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -1907,12 +1913,46 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } +static int tcp_get_msgfd(CharDriverState *chr) +{ +TCPCharDriver *s = chr-opaque; + +return s-msgfd; +} + +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) +{ +TCPCharDriver *s = chr-opaque; +struct cmsghdr *cmsg; + +for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { +int fd; + +if (cmsg-cmsg_len != CMSG_LEN(sizeof(int)) || +cmsg-cmsg_level != SOL_SOCKET || +cmsg-cmsg_type != SCM_RIGHTS) +continue; + +fd = *((int *)CMSG_DATA(cmsg)); +if (fd 0) +continue; + +if (s-msgfd != -1) +close(s-msgfd); +s-msgfd = fd; +} +} + static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr-opaque; struct msghdr msg = { 0, }; struct iovec iov[1]; +union { +struct cmsghdr cmsg; +char control[CMSG_SPACE(sizeof(int))]; +} msg_control; uint8_t buf[1024]; int len, size; @@ -1928,6 +1968,8 @@ static void tcp_chr_read(void *opaque) msg.msg_iov = iov; msg.msg_iovlen = 1; +msg.msg_control = msg_control; +msg.msg_controllen = sizeof(msg_control); size = recvmsg(s-fd, msg, 0); if (size == 0) { @@ -1940,10 +1982,16 @@ static void tcp_chr_read(void *opaque) closesocket(s-fd); s-fd = -1; } else if (size 0) { +if (s-is_unix) +unix_process_msgfd(chr, msg); if (s-do_telnetopt) tcp_chr_process_IAC_bytes(chr, s, buf, size); if (size 0) qemu_chr_read(chr, buf, size); +if (s-msgfd != -1) { +close(s-msgfd); +s-msgfd = -1; +} } } @@ -2105,12 +2153,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, s-connected = 0; s-fd = -1; s-listen_fd = -1; +s-msgfd = -1; s-is_unix = is_unix; s-do_nodelay = do_nodelay !is_unix; chr-opaque = s; chr-chr_write = tcp_chr_write; chr-chr_close = tcp_chr_close; +chr-get_msgfd = tcp_get_msgfd; if (is_listen) { s-listen_fd = fd; diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..77d4eda 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -51,6 +51,7 @@ struct CharDriverState { int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); +int (*get_msgfd)(struct CharDriverState *s); IOEventHandler *chr_event; IOCanRWHandler *chr_can_read; IOReadHandler *chr_read; @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); void qemu_chr_initial_reset(void); int qemu_chr_can_read(CharDriverState *s); void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); +int qemu_chr_get_msgfd(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Add monitor_get_fd() command for fetching named fds
Signed-off-by: Mark McLoughlin mar...@redhat.com --- monitor.c | 24 monitor.h |2 ++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index 817e4b7..6ad2e14 100644 --- a/monitor.c +++ b/monitor.c @@ -1774,6 +1774,30 @@ static void do_closefd(Monitor *mon, const char *fdname) fdname); } +int monitor_get_fd(Monitor *mon, const char *fdname) +{ +mon_fd_t *monfd; + +LIST_FOREACH(monfd, mon-fds, next) { +int fd; + +if (strcmp(monfd-name, fdname) != 0) { +continue; +} + +fd = monfd-fd; + +/* caller takes ownership of fd */ +LIST_REMOVE(monfd, next); +qemu_free(monfd-name); +qemu_free(monfd); + +return fd; +} + +return -1; +} + static const mon_cmd_t mon_cmds[] = { #include qemu-monitor.h { NULL, NULL, }, diff --git a/monitor.h b/monitor.h index 13e8cc7..f6a43c0 100644 --- a/monitor.h +++ b/monitor.h @@ -20,6 +20,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, BlockDriverCompletionFunc *completion_cb, void *opaque); +int monitor_get_fd(Monitor *mon, const char *fdname); + void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap); void monitor_printf(Monitor *mon, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Add support for fd=name to tap and socket networking
This allows a program to initialize a host networking device using a file descriptor passed over a unix monitor socket. The program must first pass the file descriptor using SCM_RIGHTS ancillary data with the getfd monitor command. It then may do host_net_add tap fd=name to use the named file descriptor. Signed-off-by: Mark McLoughlin mar...@redhat.com --- net.c | 42 +++--- 1 files changed, 35 insertions(+), 7 deletions(-) diff --git a/net.c b/net.c index 90cf912..1838692 100644 --- a/net.c +++ b/net.c @@ -2410,6 +2410,23 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, exit(exit_status); } +static int net_handle_fd_param(Monitor *mon, const char *param) +{ +if (!qemu_isdigit(param[0])) { +int fd; + +fd = monitor_get_fd(mon, param); +if (fd == -1) { +config_error(mon, No file descriptor named %s found, param); +return -1; +} + +return fd; +} else { +return strtol(param, NULL, 0); +} +} + int net_client_init(Monitor *mon, const char *device, const char *p) { char buf[1024]; @@ -2650,14 +2667,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) static const char * const fd_params[] = { vlan, name, fd, sndbuf, NULL }; +ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) 0) { config_error(mon, invalid parameter '%s' in '%s'\n, chkbuf, p); -ret = -1; goto out; } -fd = strtol(buf, NULL, 0); +fd = net_handle_fd_param(mon, buf); +if (fd == -1) { +goto out; +} fcntl(fd, F_SETFL, O_NONBLOCK); s = net_tap_fd_init(vlan, device, name, fd); +if (!s) { +close(fd); +} } else { static const char * const tap_params[] = { vlan, name, ifname, script, downscript, sndbuf, NULL @@ -2697,15 +2720,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) vlan, name, fd, NULL }; int fd; +ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) 0) { config_error(mon, invalid parameter '%s' in '%s'\n, chkbuf, p); -ret = -1; goto out; } -fd = strtol(buf, NULL, 0); -ret = -1; -if (net_socket_fd_init(vlan, device, name, fd, 1)) -ret = 0; +fd = net_handle_fd_param(mon, buf); +if (fd == -1) { +goto out; +} +if (!net_socket_fd_init(vlan, device, name, fd, 1)) { +close(fd); +goto out; +} +ret = 0; } else if (get_param_value(buf, sizeof(buf), listen, p) 0) { static const char * const listen_params[] = { vlan, name, listen, NULL -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Make tcp_chr_read() use recvmsg()
Signed-off-by: Mark McLoughlin mar...@redhat.com --- qemu-char.c | 12 +++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..e0d7220 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1911,15 +1911,25 @@ static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr-opaque; +struct msghdr msg = { 0, }; +struct iovec iov[1]; uint8_t buf[1024]; int len, size; if (!s-connected || s-max_size = 0) return; + len = sizeof(buf); if (len s-max_size) len = s-max_size; -size = recv(s-fd, (void *)buf, len, 0); + +iov[0].iov_base = buf; +iov[0].iov_len = len; + +msg.msg_iov = iov; +msg.msg_iovlen = 1; + +size = recvmsg(s-fd, msg, 0); if (size == 0) { /* connection closed */ s-connected = 0; -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] Re: [PATCH] Make tcp_chr_read() use recvmsg()
Sorry about that, wrong list clearly. Cheers, Mark. -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Problem with libvirt and pci passthrough
Mark McLoughlin schrieb: On Thu, 2009-07-16 at 13:20 +0200, Mirko Raasch wrote: On Thu, 2009-07-16 at 11:06 +0200, Mirko Raasch wrote: Hi, i´m still having problem with libvirt and pci passthrough, if i use more then one pci card in the guest. If i start qemu 0.10.5 manualy, i can use all of the pci devices in the guest, here is the log: http://nopaste.info/610fa81fb5.html If i use libvirt to start the guest and passthrough three pci device, none of the device is usable in the guest: http://nopaste.info/ccfbfcf9a0.html What does /var/log/libvirt/qemu/vdr.log say? Cheers, Mark. The log says: LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin HOME=/root USER=root LOGNAME=root /usr/bin/qemu-system-x86_64 -S -M pc -m 512 -smp 1 -name vdr -uuid 87e7c782-73c4-c0e0-2396-8514b3701a4a -monitor pty -localtime -boot c -drive file=/media/vm/vdr.img,if=ide,index=0,boot=on -net nic,macaddr=54:52:00:49:d0:64,vlan=0,model=virtio -net tap,fd=15,vlan=0 -serial pty -parallel none -usb -vnc 0.0.0.0:2 -k de -pcidevice host=05:00.0 -pcidevice host=05:01.0 -pcidevice host=05:02.0 char device redirected to /dev/pts/1 char device redirected to /dev/pts/2 It looks like libvirt is doing its job correctly. Try with managed='no' perhaps? Cheers, Mark. Ok, i gave up. There seems to be no chance to use libvirt and pci passthrough with more then one pci device. Now i start qemu with a bash script and that works fine till now. -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] VMware ESX driver progress
On Tue, Jul 21, 2009 at 04:58:50PM +0200, Matthias Bolte wrote: Hi, the development was hindered by our testing cluster being offline since 2 weeks due to server room cooling system maintenance. But I finally got a basic version of dump-XML done, that fills all fields of the virDomainDef that the VMX file contains data for. Changes since first announcement: - Move code into esx subdirectory - Add esxNodeGetInfo() - Fix esxDomainGetInfo() to report the correct value for memory - Add memory and max-memory getter/setters - Add CPU scheduler getter/setters - Validate a migration before trying to perform it - Replace esxUtil_Strdup() with strdup() and remove esxUtil_MigrateStringFromLibXML() - Add esxVI_EnsureSession() to handle expiring sessions - Separate VI client code into multiple files and generate most of the type handling code with macros - Add esxDomainDumpXML() based on esxVMX_ParseConfig() The ESX driver isn't complete yet, currently it supports: - domain lookup by ID, UUID and name - domain listing - domain info retrieval - domain suspend and resume - domain start and destroy - domain reboot and shutdown, if the VMware tools are installed inside the domain - domain migration with previous validation - domain memory configuration - domain CPU amount and scheduler configuration - domain XML-dump - domain XML-from-native (VMX) - node info retrieval - node hostname retrieval The next milestone is creating/defining a new domain from a domain XML config, but this will not be finished until feature freeze for 0.7.0 on friday. Okay, at this point since we have import/export of the XML I think embedding the driver makes sense, then the Create and others part can be added incrementally. I will make another pass on the code and hopefully we will be able to push it in by Friday, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/1] Multipath pool support
The following patch implements multipath pool support. It's very basic functionality, consisting of creating a pool that contains all the multipath devices on the host. That will cover the common case of users who just want to discover all the available multipath devices and assign them to guests. It doesn't currently allow configuration of multipathing, so for now setting the multipath configuration will have to continue to be done as part of the host system build. Example XML to create the pool is: pool type=mpath namempath/name target path/dev/mapper/path /target /pool The target element is ignored, as it is by the disk pool, but the config code rejects the XML if it does not exist. That behavior should obviously be cleaned up, but I think that should be done in a separate patch, as it's really a bug in the config code, not related to the addition of the new pool type. Dave -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/1] Add a simple pool type for multipath devices
This pool type contains volumes for the multipath devices that are present on the host. It does not (yet) support any sort of multipath configuration, so that aspect of system administration must still be done at host build time. --- configure.in| 24 +++ po/POTFILES.in |1 + src/Makefile.am |9 + src/storage_backend.c | 82 ++ src/storage_backend.h |5 +- src/storage_backend_mpath.c | 344 +++ src/storage_backend_mpath.h | 31 src/storage_conf.c |7 +- src/storage_conf.h |1 + 9 files changed, 502 insertions(+), 2 deletions(-) create mode 100644 src/storage_backend_mpath.c create mode 100644 src/storage_backend_mpath.h diff --git a/configure.in b/configure.in index 634e812..7a94373 100644 --- a/configure.in +++ b/configure.in @@ -906,6 +906,8 @@ AC_ARG_WITH([storage-iscsi], [ --with-storage-iscsiwith iSCSI backend for the storage driver (on)],[],[with_storage_iscsi=check]) AC_ARG_WITH([storage-scsi], [ --with-storage-scsi with SCSI backend for the storage driver (on)],[],[with_storage_scsi=check]) +AC_ARG_WITH([storage-mpath], +[ --with-storage-mpathwith mpath backend for the storage driver (on)],[],[with_storage_mpath=check]) AC_ARG_WITH([storage-disk], [ --with-storage-disk with GPartd Disk backend for the storage driver (on)],[],[with_storage_disk=check]) @@ -916,6 +918,7 @@ if test $with_libvirtd = no; then with_storage_lvm=no with_storage_iscsi=no with_storage_scsi=no + with_storage_mpath=no with_storage_disk=no fi if test $with_storage_dir = yes ; then @@ -1037,6 +1040,26 @@ if test $with_storage_scsi = check; then fi AM_CONDITIONAL([WITH_STORAGE_SCSI], [test $with_storage_scsi = yes]) +if test $with_storage_mpath = check; then + with_storage_mpath=yes + + AC_DEFINE_UNQUOTED([WITH_STORAGE_MPATH], 1, + [whether mpath backend for storage driver is enabled]) +fi +AM_CONDITIONAL([WITH_STORAGE_MPATH], [test $with_storage_mpath = yes]) + +if test $with_storage_mpath = yes; then + DEVMAPPER_REQUIRED=0.0 + DEVMAPPER_CFLAGS= + DEVMAPPER_LIBS= + PKG_CHECK_MODULES(DEVMAPPER, devmapper = $DEVMAPPER_REQUIRED, +[], [ +AC_MSG_ERROR( +[You must install device-mapper-devel = $DEVMAPPER_REQUIRED to compile libvirt]) +]) +fi +AC_SUBST([DEVMAPPER_CFLAGS]) +AC_SUBST([DEVMAPPER_LIBS]) LIBPARTED_CFLAGS= LIBPARTED_LIBS= @@ -1506,6 +1529,7 @@ AC_MSG_NOTICE([ NetFS: $with_storage_fs]) AC_MSG_NOTICE([ LVM: $with_storage_lvm]) AC_MSG_NOTICE([ iSCSI: $with_storage_iscsi]) AC_MSG_NOTICE([SCSI: $with_storage_scsi]) +AC_MSG_NOTICE([ mpath: $with_storage_mpath]) AC_MSG_NOTICE([Disk: $with_storage_disk]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([Security Drivers]) diff --git a/po/POTFILES.in b/po/POTFILES.in index 7ccf3ab..f70936b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -36,6 +36,7 @@ src/storage_backend_fs.c src/storage_backend_iscsi.c src/storage_backend_logical.c src/storage_backend_scsi.c +src/storage_backend_mpath.c src/storage_conf.c src/storage_driver.c src/test.c diff --git a/src/Makefile.am b/src/Makefile.am index 79826b1..57bf9ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -184,6 +184,9 @@ STORAGE_DRIVER_ISCSI_SOURCES = \ STORAGE_DRIVER_SCSI_SOURCES = \ storage_backend_scsi.h storage_backend_scsi.c +STORAGE_DRIVER_MPATH_SOURCES = \ + storage_backend_mpath.h storage_backend_mpath.c + STORAGE_DRIVER_DISK_SOURCES = \ storage_backend_disk.h storage_backend_disk.c @@ -436,6 +439,10 @@ if WITH_STORAGE_SCSI libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SCSI_SOURCES) endif +if WITH_STORAGE_MPATH +libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_MPATH_SOURCES) +endif + if WITH_STORAGE_DISK libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_DISK_SOURCES) endif @@ -495,6 +502,7 @@ EXTRA_DIST += \ $(STORAGE_DRIVER_LVM_SOURCES) \ $(STORAGE_DRIVER_ISCSI_SOURCES) \ $(STORAGE_DRIVER_SCSI_SOURCES) \ + $(STORAGE_DRIVER_MPATH_SOURCES) \ $(STORAGE_DRIVER_DISK_SOURCES) \ $(NODE_DEVICE_DRIVER_SOURCES) \ $(NODE_DEVICE_DRIVER_HAL_SOURCES) \ @@ -563,6 +571,7 @@ libvirt_la_LDFLAGS = $(VERSION_SCRIPT_FLAGS)libvirt.syms \ $(COVERAGE_CFLAGS:-f%=-Wc,-f%) \ $(LIBXML_LIBS) $(SELINUX_LIBS) \ $(XEN_LIBS) $(DRIVER_MODULE_LIBS) \ + $(DEVMAPPER_LIBS) \ @CYGWIN_EXTRA_LDFLAGS@
Re: [libvirt] How to config my VM to use KVM with libvirt?
Daniel P. Berrange wrote: On Tue, Jul 21, 2009 at 09:46:17AM -0400, Jim Paris wrote: Speaking of this, I've noticed that domain type='qemu' os type arch='i686' machine='pc'hvm/type /os /domain runs WITH kvm on an x86_64 system. Is that intended? No, its not intended ! ... I'm actually wondering why we bother with #1 at all. If the binary has '-no-kvm' and the domain is 'qemu', then it should be used no matter what arch. Agreed. Below is a patch which should fix the oversight (lightly tested). However, this is going to be a user-visible change and may cause people to complain that their existing 32-bit domains are unexpectedly running with -no-kvm. Is that OK? Technically it's a misconfiguration. For the record, I think we've already broken this area once when 0.6.2 came out -- previous to that, even my 64-bit VMs had domain type qemu, and libvirt ran my specified kvm binary without -no-kvm. -jim From f7edd4c887512e4fc7c97b12a4f2409244af9eb3 Mon Sep 17 00:00:00 2001 From: Jim Paris j...@jtan.com Date: Tue, 21 Jul 2009 17:07:51 -0400 Subject: [PATCH] Always add -no-kvm and -no-kqemu, if available, for qemu domains. If the qemu binary supports -no-kvm and/or -no-kqemu, they should always be added for plain qemu domains. Previously, we omitted them whenever the host and guest architectures implied that they would be disabled automatically, but that logic was flawed in some cases (such as i686 and x86_64). Signed-off-by: Jim Paris j...@jtan.com --- src/qemu_conf.c | 12 1 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/qemu_conf.c b/src/qemu_conf.c index 4043d70..f146598 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -977,22 +977,18 @@ int qemudBuildCommandLine(virConnectPtr conn, emulator = def-emulator; /* Need to explicitly disable KQEMU if - * 1. Arch matches host arch - * 2. Guest domain is 'qemu' - * 3. The qemu binary has the -no-kqemu flag + * 1. Guest domain is 'qemu' + * 2. The qemu binary has the -no-kqemu flag */ if ((qemuCmdFlags QEMUD_CMD_FLAG_KQEMU) -STREQ(ut.machine, def-os.arch) def-virtType == VIR_DOMAIN_VIRT_QEMU) disableKQEMU = 1; /* Need to explicitly disable KVM if - * 1. Arch matches host arch - * 2. Guest domain is 'qemu' - * 3. The qemu binary has the -no-kvm flag + * 1. Guest domain is 'qemu' + * 2. The qemu binary has the -no-kvm flag */ if ((qemuCmdFlags QEMUD_CMD_FLAG_KVM) -STREQ(ut.machine, def-os.arch) def-virtType == VIR_DOMAIN_VIRT_QEMU) disableKVM = 1; -- 1.6.1.3 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Support physical memory in virDomainMemoryPeek()
Hi, This patch provides support for physical memory in virDomainMemoryPeek(). Please consider applying. Signed-off-by: Nguyen Anh Quynh aqu...@gmail.com # diffstat pmemsave3.diff docs/libvirt-api.xml |2 +- include/libvirt/libvirt.h.in |1 + src/libvirt.c| 14 +- src/qemu_driver.c| 17 - 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/docs/libvirt-api.xml b/docs/libvirt-api.xml index 8ded57a..04b1108 100644 --- a/docs/libvirt-api.xml +++ b/docs/libvirt-api.xml @@ -1268,7 +1268,7 @@ see note above'/ arg name='uuidstr' type='const char *' info='the string UUID for the domain'/ /function function name='virDomainMemoryPeek' file='libvirt' module='libvirt' - infoThis function allows you to read the contents of a domainapos;s memory. The memory which is read is controlled by the apos;startapos;, apos;sizeapos; and apos;flagsapos; parameters. If apos;flagsapos; is VIR_MEMORY_VIRTUAL then the apos;startapos; and apos;sizeapos; parameters are interpreted as virtual memory addresses for whichever task happens to be running on the domain at the moment. Although this sounds haphazard it is in fact what you want in order to read Linux kernel state, because it ensures that pointers in the kernel image can be interpreted coherently. apos;bufferapos; is the return buffer and must be at least apos;sizeapos; bytes. apos;sizeapos; may be 0 to test if the call would succeed. NB. The remote driver imposes a 64K byte limit on apos;sizeapos;. For your program to be able to work reliably over a remote connection you should split large requests to lt;= 65536 bytes./info + infoThis function allows you to read the contents of a domainapos;s memory. The memory which is read is controlled by the apos;startapos;, apos;sizeapos; and apos;flagsapos; parameters. To read physical memory, specify VIR_MEMORY_PHYSICAL as flags value. On the other hands, if apos;flagsapos; is VIR_MEMORY_VIRTUAL then the apos;startapos; and apos;sizeapos; parameters are interpreted as virtual memory addresses for whichever task happens to be running on the domain at the moment. Although this sounds haphazard it is in fact what you want in order to read Linux kernel state, because it ensures that pointers in the kernel image can be interpreted coherently. apos;bufferapos; is the return buffer and must be at least apos;sizeapos; bytes. apos;sizeapos; may be 0 to test if the call would succeed. NB. The remote driver imposes a 64K byte limit on apos;sizeapos;. For your program to be able to work reliably over a remote connection you should split large requests to lt;= 65536 bytes./info return type='int' info='0 in case of success or -1 in case of failure. really 64 bits'/ arg name='dom' type='virDomainPtr' info='pointer to the domain object'/ arg name='start' type='unsigned long long' info='start of memory to peek'/ diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index ba2b6f0..e6536c7 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -619,6 +619,7 @@ int virDomainBlockPeek (virDomainPtr dom, /* Memory peeking flags. */ typedef enum { VIR_MEMORY_VIRTUAL = 1, /* addresses are virtual addresses */ + VIR_MEMORY_PHYSICAL = 2, /* addresses are physical addresses */ } virDomainMemoryFlags; int virDomainMemoryPeek (virDomainPtr dom, diff --git a/src/libvirt.c b/src/libvirt.c index f4a7fa7..393d0c1 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3815,19 +3815,20 @@ virDomainMemoryPeek (virDomainPtr dom, goto error; } -/* Flags must be VIR_MEMORY_VIRTUAL at the moment. - * - * Note on access to physical memory: A VIR_MEMORY_PHYSICAL flag is +/* Note on access to physical memory: A VIR_MEMORY_PHYSICAL flag is * a possibility. However it isn't really useful unless the caller * can also access registers, particularly CR3 on x86 in order to * get the Page Table Directory. Since registers are different on * every architecture, that would imply another call to get the * machine registers. * - * The QEMU driver handles only VIR_MEMORY_VIRTUAL, mapping it + * The QEMU driver handles VIR_MEMORY_VIRTUAL, mapping it * to the qemu 'memsave' command which does the virtual to physical * mapping inside qemu. * + * The QEMU driver also handles VIR_MEMORY_PHYSICAL, mapping it + * to the qemu 'pmemsave' command. + * * At time of writing there is no Xen driver. However the Xen * hypervisor only lets you map physical pages from other domains, * and so the Xen driver would have to do the virtual to physical @@ -3836,11 +3837,6 @@ virDomainMemoryPeek (virDomainPtr dom, * which does this, although we cannot copy this code directly * because of incompatible licensing. */ -
[libvirt] [PATCH 0/4] Fixes to some bugs encountered testing virInterface*
This series of patches fixes some problems I found while testing the virInterface implementation. Note that the 3rd patch in the series only fixes virInterface-related instances of the problem (releasing the conn lock before reporting errors). If that patch is approved, a similar thing must be done for several other functions in datatypes.c. -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/4] rename variable called 'interface' to 'iface'
This avoids a problem when building under MINGW32 --- src/virsh.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/virsh.c b/src/virsh.c index 91f5b5a..bae0c66 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -3307,7 +3307,7 @@ static const vshCmdOptDef opts_interface_define[] = { static int cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) { -virInterfacePtr interface; +virInterfacePtr iface; char *from; int found; int ret = TRUE; @@ -3323,12 +3323,12 @@ cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, buffer) 0) return FALSE; -interface = virInterfaceDefineXML(ctl-conn, buffer, 0); +iface = virInterfaceDefineXML(ctl-conn, buffer, 0); free (buffer); -if (interface != NULL) { +if (iface != NULL) { vshPrint(ctl, _(Interface %s defined from %s\n), - virInterfaceGetName(interface), from); + virInterfaceGetName(iface), from); } else { vshError(ctl, FALSE, _(Failed to define interface from %s), from); ret = FALSE; -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/4] Update modified mac address in place in virGetInterface
If the mac address of an interface is changed, we must either create a new virInterface object in the cache that has the new name/mac, or modify the existing object in the cache. Because the cache is in a hash that's indexed by name only, we can't create a new entry having the same name without destroying the old one first (which isn't a possibility as someone else is already referencing the old one), so we're stuck modifying the existing entry. We have to do that without changing the pointer to the mac though, so we really can only do it if the length of the new mac is equal to or less than the old mac. Otherwise, we have to just bail. Fixing this problem to properly handle this corner case would require a hash table that used both name and mac as keys, but that would be inefficient (using the existing hash table implementation, which only allows a single key), and probably unnecessary, as the length of mac for any given interface will never change in practice. --- src/datatypes.c | 33 - 1 files changed, 32 insertions(+), 1 deletions(-) diff --git a/src/datatypes.c b/src/datatypes.c index 5f90aad..000fa66 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -535,7 +535,38 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) { ret = (virInterfacePtr) virHashLookup(conn-interfaces, name); -if ((ret == NULL) || STRCASENEQ(ret-mac, mac)) { +if (ret != NULL) { +if (STRCASENEQ(ret-mac, mac)) { +/* + * If the mac address has changed, try to modify it in + * place, which will only work if the new mac is the + * same length as, or shorter than, the old mac. + */ +size_t newmaclen = strlen(mac); +size_t oldmaclen = strlen(ret-mac); +if (newmaclen = oldmaclen) { +strcpy(ret-mac, mac); +} else { +/* + * If it's longer, we're kind of screwed, because we + * can't add a new hashtable entry (it would clash + * with the existing entry of same name), and we can't + * free/re-alloc the existing entry's mac, as some + * other thread may already be using the existing mac + * pointer. Fortunately, this should never happen, + * since the length of the mac address for any + * interface is determined by the type of the + * interface, and that is unlikely to change. + */ +virMutexUnlock(conn-lock); +virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, +Failed to change interface mac address from %s to %s due to differing lengths., +ret-mac, mac); +ret = NULL; +goto error; +} +} +} else { if (VIR_ALLOC(ret) 0) { virReportOOMError(conn); goto error; -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 3/4] Release conn lock before reporting errors in vir(Get|Release)Interface
Since virRaiseErrorFull needs to lock the conn, we must take care to call it with the lock *not* held. If this patch is approved, similar patches need to be done for other types in datatypes.c --- src/datatypes.c | 29 +++-- 1 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/datatypes.c b/src/datatypes.c index 000fa66..ba5401d 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -568,16 +568,19 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) { } } else { if (VIR_ALLOC(ret) 0) { +virMutexUnlock(conn-lock); virReportOOMError(conn); goto error; } ret-name = strdup(name); if (ret-name == NULL) { +virMutexUnlock(conn-lock); virReportOOMError(conn); goto error; } ret-mac = strdup(mac); if (ret-mac == NULL) { +virMutexUnlock(conn-lock); virReportOOMError(conn); goto error; } @@ -586,6 +589,7 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) { ret-conn = conn; if (virHashAddEntry(conn-interfaces, name, ret) 0) { +virMutexUnlock(conn-lock); virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, _(failed to add interface to connection hash table)); goto error; @@ -597,7 +601,6 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) { return(ret); error: -virMutexUnlock(conn-lock); if (ret != NULL) { VIR_FREE(ret-name); VIR_FREE(ret-mac); @@ -623,24 +626,30 @@ virReleaseInterface(virInterfacePtr iface) { virConnectPtr conn = iface-conn; DEBUG(release interface %p %s, iface, iface-name); -if (virHashRemoveEntry(conn-interfaces, iface-name, NULL) 0) +if (virHashRemoveEntry(conn-interfaces, iface-name, NULL) 0) { +/* unlock before reporting error because error report grabs lock */ +virMutexUnlock(conn-lock); virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, _(interface missing from connection hash table)); +/* don't decr the conn refct if we weren't connected to it */ +conn = NULL; +} iface-magic = -1; VIR_FREE(iface-name); VIR_FREE(iface-mac); VIR_FREE(iface); -DEBUG(unref connection %p %d, conn, conn-refs); -conn-refs--; -if (conn-refs == 0) { -virReleaseConnect(conn); -/* Already unlocked mutex */ -return; +if (conn) { +DEBUG(unref connection %p %d, conn, conn-refs); +conn-refs--; +if (conn-refs == 0) { +virReleaseConnect(conn); +/* Already unlocked mutex */ +return; +} +virMutexUnlock(conn-lock); } - -virMutexUnlock(conn-lock); } -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 4/4] Fix multiple vir*Ptr memory leaks in virsh.c
I noticed that one of my virInterface commandline functions in virsh.c was forgetting to call virInterfaceFree() before it was done, and since I had written it with copy-paste, I decided to check other functions in virsh.c for the same problem. Unless I misunderstand the APIs, I found a whole bunch of similar leaks of virDomain, virStoragePool, virNodeDevice, etc. --- src/virsh.c | 32 +++- 1 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/virsh.c b/src/virsh.c index bae0c66..fff73a1 100644 --- a/src/virsh.c +++ b/src/virsh.c @@ -784,8 +784,10 @@ cmdDomblkstat (vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain (ctl, cmd, name))) return FALSE; -if (!(device = vshCommandOptString (cmd, device, NULL))) +if (!(device = vshCommandOptString (cmd, device, NULL))) { +virDomainFree(dom); return FALSE; +} if (virDomainBlockStats (dom, device, stats, sizeof stats) == -1) { vshError (ctl, FALSE, _(Failed to get block stats %s %s), @@ -840,8 +842,10 @@ cmdDomIfstat (vshControl *ctl, const vshCmd *cmd) if (!(dom = vshCommandOptDomain (ctl, cmd, name))) return FALSE; -if (!(device = vshCommandOptString (cmd, interface, NULL))) +if (!(device = vshCommandOptString (cmd, interface, NULL))) { +virDomainFree(dom); return FALSE; +} if (virDomainInterfaceStats (dom, device, stats, sizeof stats) == -1) { vshError (ctl, FALSE, _(Failed to get interface stats %s %s), @@ -2528,6 +2532,7 @@ cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd) else vshPrint(ctl, _(Network %s unmarked as autostarted\n), name); +virNetworkFree(network); return TRUE; } @@ -2570,6 +2575,7 @@ cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd) if (network != NULL) { vshPrint(ctl, _(Network %s created from %s\n), virNetworkGetName(network), from); +virNetworkFree(network); } else { vshError(ctl, FALSE, _(Failed to create network from %s), from); ret = FALSE; @@ -2617,6 +2623,7 @@ cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd) if (network != NULL) { vshPrint(ctl, _(Network %s defined from %s\n), virNetworkGetName(network), from); +virNetworkFree(network); } else { vshError(ctl, FALSE, _(Failed to define network from %s), from); ret = FALSE; @@ -2997,6 +3004,7 @@ cmdNetworkStart(vshControl *ctl, const vshCmd *cmd) virNetworkGetName(network)); ret = FALSE; } +virNetworkFree(network); return ret; } @@ -3035,6 +3043,7 @@ cmdNetworkUndefine(vshControl *ctl, const vshCmd *cmd) ret = FALSE; } +virNetworkFree(network); return ret; } @@ -3071,6 +3080,7 @@ cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd) else vshError(ctl, FALSE, %s, _(failed to get network UUID)); +virNetworkFree(network); return TRUE; } @@ -3329,6 +3339,7 @@ cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) if (iface != NULL) { vshPrint(ctl, _(Interface %s defined from %s\n), virInterfaceGetName(iface), from); +virInterfaceFree (iface); } else { vshError(ctl, FALSE, _(Failed to define interface from %s), from); ret = FALSE; @@ -3498,6 +3509,7 @@ cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd) else vshPrint(ctl, _(Pool %s unmarked as autostarted\n), name); +virStoragePoolFree(pool); return TRUE; } @@ -3541,6 +3553,7 @@ cmdPoolCreate(vshControl *ctl, const vshCmd *cmd) if (pool != NULL) { vshPrint(ctl, _(Pool %s created from %s\n), virStoragePoolGetName(pool), from); +virStoragePoolFree(pool); } else { vshError(ctl, FALSE, _(Failed to create pool from %s), from); ret = FALSE; @@ -3594,6 +3607,7 @@ cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd) if (dev != NULL) { vshPrint(ctl, _(Node device %s created from %s\n), virNodeDeviceGetName(dev), from); +virNodeDeviceFree(dev); } else { vshError(ctl, FALSE, _(Failed to create node device from %s), from); ret = FALSE; @@ -3801,6 +3815,7 @@ cmdPoolDefine(vshControl *ctl, const vshCmd *cmd) if (pool != NULL) { vshPrint(ctl, _(Pool %s defined from %s\n), virStoragePoolGetName(pool), from); +virStoragePoolFree(pool); } else { vshError(ctl, FALSE, _(Failed to define pool from %s), from); ret = FALSE; @@ -3960,9 +3975,9 @@ cmdPoolDelete(vshControl *ctl, const vshCmd *cmd) } else { vshError(ctl, FALSE, _(Failed to delete pool %s), name); ret = FALSE; -virStoragePoolFree(pool); } +virStoragePoolFree(pool); return ret; } @@ -4460,6 +4475,8 @@ cmdPoolStart(vshControl *ctl, const
[libvirt] OpenVZ : cannot assign bridge to any interface
Hi, I'm bit confuing between 2 problems with libvirt-0.6.5 for OpenVZ. [1] bridge was created but no interface assigned to it [2] virsh dumpxml returns xml in which type is qemu [1] - I tried libvirt-0.6.5 on Fedora8 to create OpenVZ container ( OpenVZ kernel is linux-2.6.18 ). A bridge was seemed to successfully create but no interface could not be assigned to the bridge. Due to that, ping could not reach the guest in container(10.0.1.2). ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [r...@node13 test]# brctl show bridge name bridge id STP enabled interfaces br101 8000. no [r...@node13 test]# ifconfig -a br101 Link encap:Ethernet HWaddr 00:00:00:00:00:00 inet addr:10.0.1.1 Bcast:10.0.1.15 Mask:255.255.255.240 inet6 addr: fe80::200:ff:fe00:0/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:30 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:5031 (4.9 KiB) eth0 Link encap:Ethernet HWaddr 00:1C:C4:xx:xx:xx inet addr:133.xx.xx.xx Bcast:133.xx.xx.xx Mask:255.255.255.0 inet6 addr: fe80::21c:c4ff::/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:196949 errors:0 dropped:0 overruns:0 frame:0 TX packets:64300 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:228373526 (217.7 MiB) TX bytes:5652593 (5.3 MiB) Interrupt:169 eth1 Link encap:Ethernet HWaddr 00:1C:C4:xx:xx:xx BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) Interrupt:50 loLink encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:323 errors:0 dropped:0 overruns:0 frame:0 TX packets:323 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:29949 (29.2 KiB) TX bytes:29949 (29.2 KiB) sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) venet0Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 UP BROADCAST POINTOPOINT RUNNING NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) veth101 Link encap:Ethernet HWaddr 52:54:00:52:C3:FF inet6 addr: fe80::5054:ff:fe52:c3ff/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ The followings are python script and xml that I tested with. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [r...@node13 test]# cat test.py import libvirt conn = libvirt.open('openvz:///system') conn.networkDefineXML( file('net.xml').read() ) conn.defineXML( file('test.xml').read() ) net = conn.networkLookupByName('guestnet101') net.create() guest = conn.lookupByName('101') guest.create() [r...@node13 test]# cat test.xml domain type='openvz' id='101' name101/name os typeexe/type init/sbin/fakeinit.sh/init /os memory524288/memory devices filesystem type='template' source name='fedora-10-x86_64'/ target dir='/'/ /filesystem console type='pty'/ interface type='bridge' mac address=52:54:00:00:01:01 / source bridge='guestnet101'/ target dev='veth101'/ /interface /devices /domain [r...@node13 test]# cat net.xml network nameguestnet101/name bridge name=br101 stp=off / forward mode=nat/ ip address=10.0.1.1 netmask=255.255.255.240 dhcp range start=10.0.1.2 end=10.0.1.2 / /dhcp /ip /network ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [2] - I guess type in domain must be 'openvz' but virsh dumpxml returns it as 'qemu'. ( The configuration of VE 101 remains in [1] ) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [r...@node13 test]# virsh dumpxml 101 domain type='qemu' id='101' name101/name uuiddedee02b-b74f-6e43-f5ec-27050986efa8/uuid memory0/memory currentMemory0/currentMemory vcpu1/vcpu os typeexe/type init/sbin/init/init /os clock