[libvirt] [PATCH 0/2] about Virsh Command Reference
by Hu Tao
Hi,
We now have libvirt advanced at 0.9.3, but there is almost no
progress has been made on Virsh Command Reference. I'm now
starting on updating Virsh Command Reference to get it synced
with libvirt/virsh, but since I'm not a native-English speaker,
there must be grammers, typos, etc. in the documents written
by me, so any comments on these are appreciated. Besides,
comments on other errors, such as example usages, are also
welcome.
In this series, docs for two cmmands are updated. I'll post more
patches for other commands subsequently.
Hu Tao (2):
update documentation for command attach-disk
update documentation for command detach-disk
source/attach-disk.xml | 292 +++++++++++++++++++++++++++++++++++++++++++++++-
source/detach-disk.xml | 233 +++++++++++++++++++++++++++++++++++++-
2 files changed, 517 insertions(+), 8 deletions(-)
--
1.7.3.1
13 years, 4 months
[libvirt] [PATCHv2 1/2] xml: Print file name on parse error
by Peter Krempa
This patch prints file name of currently parsed document
if an parse error occurs. While parsing XML documments from
string, user may specify NULL as URL and the original error message
(not containing filename information) is printed.
Fixes BZ #726771
---
src/util/xml.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/util/xml.c b/src/util/xml.c
index 05317ea..48fc3cf 100644
--- a/src/util/xml.c
+++ b/src/util/xml.c
@@ -647,10 +647,18 @@ catchXMLError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
if (virGetLastError() == NULL &&
ctxt->lastError.level == XML_ERR_FATAL &&
ctxt->lastError.message != NULL) {
- virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
- _("at line %d: %s"),
- ctxt->lastError.line,
- ctxt->lastError.message);
+ if (ctxt->lastError.file) {
+ virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
+ _("%s:%d: %s"),
+ ctxt->lastError.file,
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ } else {
+ virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
+ _("at line %d: %s"),
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ }
}
}
}
--
1.7.3.4
13 years, 4 months
[libvirt] [PATCH 1/2] xml: Print file name on parse error
by Peter Krempa
This patch prints file name of currently parsed document
if an parse error occurs. While parsing XML documments from
string, user may specify NULL as URL and the original error message
(not containing filename information) is printed.
Fixes BZ #726771
---
src/util/xml.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/util/xml.c b/src/util/xml.c
index 05317ea..0e93d48 100644
--- a/src/util/xml.c
+++ b/src/util/xml.c
@@ -647,10 +647,18 @@ catchXMLError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
if (virGetLastError() == NULL &&
ctxt->lastError.level == XML_ERR_FATAL &&
ctxt->lastError.message != NULL) {
- virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
- _("at line %d: %s"),
- ctxt->lastError.line,
- ctxt->lastError.message);
+ if (ctxt->lastError.file) {
+ virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
+ _("in file \'%s\'at line %d: %s"),
+ ctxt->lastError.file,
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ } else {
+ virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
+ _("at line %d: %s"),
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ }
}
}
}
--
1.7.3.4
13 years, 4 months
[libvirt] [PATCH 1/2] xml: Print file name on parse error
by Peter Krempa
This patch prints file name of currently parsed document
if an parse error occurs. While parsing XML documments from
string, user may specify NULL as URL and the original error message
(not containing filename information) is printed.
Fixes BZ #726771
---
src/util/xml.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/util/xml.c b/src/util/xml.c
index 05317ea..48fc3cf 100644
--- a/src/util/xml.c
+++ b/src/util/xml.c
@@ -647,10 +647,18 @@ catchXMLError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
if (virGetLastError() == NULL &&
ctxt->lastError.level == XML_ERR_FATAL &&
ctxt->lastError.message != NULL) {
- virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
- _("at line %d: %s"),
- ctxt->lastError.line,
- ctxt->lastError.message);
+ if (ctxt->lastError.file) {
+ virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
+ _("%s:%d: %s"),
+ ctxt->lastError.file,
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ } else {
+ virGenericReportError(domcode, VIR_ERR_XML_DETAIL,
+ _("at line %d: %s"),
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ }
}
}
}
--
1.7.3.4
13 years, 4 months
[libvirt] [PATCH RFC 00/10] API && XML to control virtual link state of guest NICs
by Peter Krempa
Hypervisors provide means for controling link state of virtual NICs. Ability
to control this can be usefully used for various aplications. These patches
add (or propose) an API for controling link states of these nics.
API functions added:
-----------------------------------------------------------------------
int virDomainInterfaceLinkSetState(virDomainPtr dom,
const char *path,
unsigned int state,
unsigned int flags);
This function sets link state for a NIC. A NIC is identified by the domain and
path (which is MAC address of the NIC (in a string representation)).
States are represented by the virInterfaceLinkStates enum.
Flags determine manipulation impact of the command (live/persistent).
int virDomainInterfaceLinkGetState(virDomainPtr dom,
const char *path,
unsigned int flags);
This function requests the interface state and returns it
as the return value.
Peter Krempa (10):
linkstate: XML for modification of interface's link state.
linkstate: Public API for modifying link state on interfaces
linkstate: Internal API for interface link state
linkstate: Implementation of the public API
linkstate: Wire up the remote protocol
linkstate: Add parsing code for new XML element
linkstate: Add usage of the new api to virsh
linkstate: qemu: Add monitor support for setting link state
linkstate: qemu: Add detection of link state setting capability.
linkstate: qemu: Add link state modification support to qemu driver.
docs/formatdomain.html.in | 21 ++++
- add examples for the new element
docs/schemas/domain.rng | 11 ++
- add grammar for the new element
include/libvirt/libvirt.h.in | 24 +++++
- add public API headers
- add link states enum
src/conf/domain_conf.c | 19 ++++
src/conf/domain_conf.h | 1 +
- add new element and propertyto parsing and
generating of domain configs
src/driver.h | 14 +++-
src/libvirt.c | 122 ++++++++++++++++++++++
src/libvirt_public.syms | 6 +
- add implementation and expose public symbols
src/qemu/qemu_capabilities.c | 5 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_driver.c | 228 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 19 ++++
src/qemu/qemu_monitor.h | 3 +
src/qemu/qemu_monitor_json.c | 23 ++++
src/qemu/qemu_monitor_json.h | 4 +
src/qemu/qemu_monitor_text.c | 47 +++++++++
src/qemu/qemu_monitor_text.h | 4 +
src/qemu/qemu_process.c | 37 +++++++
- add support for qemu driver
src/remote/remote_driver.c | 2 +
src/remote/remote_protocol.x | 21 ++++-
src/remote_protocol-structs | 16 +++
- remote protocol support for new API
tools/virsh.c | 120 ++++++++++++++++++++++
tools/virsh.pod | 11 ++
- add comands to virsh and documentation
23 files changed, 757 insertions(+), 2 deletions(-)
--
1.7.6
13 years, 4 months
[libvirt] [PATCH v3] Implement DNS SRV record into the bridge driver
by Michal Novotny
Hi,
this is the third version of my patch to the bridge driver and
libvirt XML file to include support for the SRV records in the DNS.
The syntax is based on DNSMasq man page and tests for both xml2xml
and xml2argv were added as well.
Differences between v2 and v3:
- Rebased for the latest version of libvirt (incl. commit
4a6ffae3b64287e63cab6f1ab40d162dcd898333 by Laine Stump)
- Moved the VIR_FREE() call in virNetworkDNSDefFree() to
the right location, i.e. after the condition there
Differences between v1 and v2:
- A minor rewrite of integer parsing functionality
- Extend tests to test with both minimal and full set of attributes
- Check for service name length implemented
Signed-off-by: Michal Novotny <minovotn(a)redhat.com>
---
docs/formatnetwork.html.in | 12 ++
docs/schemas/network.rng | 26 ++++
src/conf/network_conf.c | 130 +++++++++++++++++++-
src/conf/network_conf.h | 16 +++
src/network/bridge_driver.c | 43 +++++++
.../nat-network-dns-srv-record-minimal.argv | 1 +
.../nat-network-dns-srv-record-minimal.xml | 26 ++++
.../nat-network-dns-srv-record.argv | 1 +
.../nat-network-dns-srv-record.xml | 26 ++++
tests/networkxml2argvtest.c | 2 +
.../nat-network-dns-srv-record-minimal.xml | 26 ++++
.../nat-network-dns-srv-record.xml | 26 ++++
.../nat-network-dns-srv-record-minimal.xml | 26 ++++
.../nat-network-dns-srv-record.xml | 26 ++++
tests/networkxml2xmltest.c | 2 +
15 files changed, 387 insertions(+), 2 deletions(-)
create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.xml
create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.argv
create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.xml
create mode 100644 tests/networkxml2xmlin/nat-network-dns-srv-record-minimal.xml
create mode 100644 tests/networkxml2xmlin/nat-network-dns-srv-record.xml
create mode 100644 tests/networkxml2xmlout/nat-network-dns-srv-record-minimal.xml
create mode 100644 tests/networkxml2xmlout/nat-network-dns-srv-record.xml
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 99031d0..51b1581 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -342,6 +342,7 @@
<mac address='00:16:3E:5D:C7:9E'/>
<dns>
<txt name="example" value="example value" />
+ <srv service="name" protocol="tcp" domain="test-domain-name" target="." port="1024" priority="10" weight="10"/>
</dns>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
@@ -390,6 +391,17 @@
<span class="since">Since 0.9.3</span>
</dd>
</dl>
+ <dl>
+ <dt><code>srv</code></dt>
+ <dd>The <code>dns</code> element can have also 0 or more <code>srv</code>
+ record elements. Each <code>srv</code> record element defines a DNS SRV record
+ and has 2 mandatory and 5 optional attributes. The mandatory attributes
+ are service name and protocol (tcp, udp) and the optional attributes are
+ target, port, priority, weight and domain as defined in DNS server SRV
+ RFC (RFC 2782).
+ <span class="since">Since 0.9.5</span>
+ </dd>
+ </dl>
</dd>
<dt><code>ip</code></dt>
<dd>The <code>address</code> attribute defines an IPv4 address in
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 1c44471..dae2799 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -138,6 +138,19 @@
</element>
</zeroOrMore>
<zeroOrMore>
+ <element name="srv">
+ <attribute name="service"><text/></attribute>
+ <attribute name="protocol"><ref name="protocol"/></attribute>
+ <optional>
+ <attribute name="domain"><ref name="dnsName"/></attribute>
+ <attribute name="target"><text/></attribute>
+ <attribute name="port"><ref name="unsignedShort"/></attribute>
+ <attribute name="priority"><ref name="unsignedShort"/></attribute>
+ <attribute name="weight"><ref name="unsignedShort"/></attribute>
+ </optional>
+ </element>
+ </zeroOrMore>
+ <zeroOrMore>
<element name="host">
<attribute name="ip"><ref name="ipv4Addr"/></attribute>
<oneOrMore>
@@ -206,6 +219,19 @@
</element>
</define>
+ <define name='unsignedShort'>
+ <data type='integer'>
+ <param name="minInclusive">0</param>
+ <param name="maxInclusive">65535</param>
+ </data>
+ </define>
+
+ <define name='protocol'>
+ <data type='string'>
+ <param name='pattern'>(tcp)|(udp)</param>
+ </data>
+ </define>
+
<define name='addr-family'>
<data type='string'>
<param name="pattern">(ipv4)|(ipv6)</param>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index e055094..6399db4 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -137,6 +137,15 @@ static void virNetworkDNSDefFree(virNetworkDNSDefPtr def)
}
}
VIR_FREE(def->hosts);
+ if (def->nsrvrecords) {
+ while (def->nsrvrecords--) {
+ VIR_FREE(def->srvrecords[def->nsrvrecords].domain);
+ VIR_FREE(def->srvrecords[def->nsrvrecords].service);
+ VIR_FREE(def->srvrecords[def->nsrvrecords].protocol);
+ VIR_FREE(def->srvrecords[def->nsrvrecords].target);
+ }
+ }
+ VIR_FREE(def->srvrecords);
VIR_FREE(def);
}
}
@@ -552,8 +561,99 @@ error:
}
static int
+virNetworkDNSSrvDefParseXML(virNetworkDNSDefPtr def,
+ xmlNodePtr cur,
+ xmlXPathContextPtr ctxt)
+{
+ char *domain;
+ char *service;
+ char *protocol;
+ char *target;
+ int port;
+ int priority;
+ int weight;
+ int ret = 0;
+ char xpath[1024] = { 0 };
+
+ if (!(service = virXMLPropString(cur, "service"))) {
+ virNetworkReportError(VIR_ERR_XML_DETAIL,
+ "%s", _("Missing required service attribute in dns srv record"));
+ goto error;
+ }
+
+ if (strlen(service) > DNS_RECORD_LENGTH_SRV) {
+ virNetworkReportError(VIR_ERR_XML_DETAIL,
+ "%s", _("Service name is too long, limit is %d bytes"), DNS_RECORD_LENGTH_SRV);
+ goto error;
+ }
+
+ if (!(protocol = virXMLPropString(cur, "protocol"))) {
+ virNetworkReportError(VIR_ERR_XML_DETAIL,
+ _("Missing required protocol attribute in dns srv record '%s'"), service);
+ goto error;
+ }
+
+ /* Check whether protocol value is the supported one */
+ if (STRNEQ(protocol, "tcp") && (STRNEQ(protocol, "udp"))) {
+ virNetworkReportError(VIR_ERR_XML_DETAIL,
+ _("Invalid protocol attribute value '%s'"), protocol);
+ goto error;
+ }
+
+ if (VIR_REALLOC_N(def->srvrecords, def->nsrvrecords + 1) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+
+ def->srvrecords[def->nsrvrecords].service = service;
+ def->srvrecords[def->nsrvrecords].protocol = protocol;
+ def->srvrecords[def->nsrvrecords].domain = NULL;
+ def->srvrecords[def->nsrvrecords].target = NULL;
+ def->srvrecords[def->nsrvrecords].port = 0;
+ def->srvrecords[def->nsrvrecords].priority = 0;
+ def->srvrecords[def->nsrvrecords].weight = 0;
+
+ /* Following attributes are optional but we had to make sure their NULL above */
+ if ((target = virXMLPropString(cur, "target")) && (domain = virXMLPropString(cur, "domain"))) {
+ snprintf(xpath, sizeof(xpath), "string(//network/dns/srv[@service='%s']/@port)", service);
+ if (virXPathInt(xpath, ctxt, &port))
+ def->srvrecords[def->nsrvrecords].port = port;
+
+ snprintf(xpath, sizeof(xpath), "string(//network/dns/srv[@service='%s']/@priority)", service);
+ if (virXPathInt(xpath, ctxt, &priority))
+ def->srvrecords[def->nsrvrecords].priority = priority;
+
+ snprintf(xpath, sizeof(xpath), "string(//network/dns/srv[@service='%s']/@weight)", service);
+ if (virXPathInt(xpath, ctxt, &weight))
+ def->srvrecords[def->nsrvrecords].weight = weight;
+
+ def->srvrecords[def->nsrvrecords].domain = domain;
+ def->srvrecords[def->nsrvrecords].target = target;
+ def->srvrecords[def->nsrvrecords].port = port;
+ def->srvrecords[def->nsrvrecords].priority = priority;
+ def->srvrecords[def->nsrvrecords].weight = weight;
+ }
+
+ def->nsrvrecords++;
+
+ goto cleanup;
+
+error:
+ VIR_FREE(domain);
+ VIR_FREE(service);
+ VIR_FREE(protocol);
+ VIR_FREE(target);
+
+ ret = 1;
+
+cleanup:
+ return ret;
+}
+
+static int
virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef,
- xmlNodePtr node)
+ xmlNodePtr node,
+ xmlXPathContextPtr ctxt)
{
xmlNodePtr cur;
int ret = -1;
@@ -598,6 +698,11 @@ virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef,
name = NULL;
value = NULL;
} else if (cur->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(cur->name, BAD_CAST "srv")) {
+ ret = virNetworkDNSSrvDefParseXML(def, cur, ctxt);
+ if (ret < 0)
+ goto error;
+ } else if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "host")) {
ret = virNetworkDNSHostsDefParseXML(def, cur);
if (ret < 0)
@@ -888,7 +993,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
dnsNode = virXPathNode("./dns", ctxt);
if (dnsNode != NULL) {
- if (virNetworkDNSDefParseXML(&def->dns, dnsNode) < 0)
+ if (virNetworkDNSDefParseXML(&def->dns, dnsNode, ctxt) < 0)
goto error;
}
@@ -1147,6 +1252,27 @@ virNetworkDNSDefFormat(virBufferPtr buf,
def->txtrecords[i].value);
}
+ for (i = 0 ; i < def->nsrvrecords ; i++) {
+ if (def->srvrecords[i].service && def->srvrecords[i].protocol) {
+ virBufferAsprintf(buf, " <srv service='%s' protocol='%s' ",
+ def->srvrecords[i].service,
+ def->srvrecords[i].protocol);
+
+ if (def->srvrecords[i].domain)
+ virBufferAsprintf(buf, "domain='%s' ", def->srvrecords[i].domain);
+ if (def->srvrecords[i].target)
+ virBufferAsprintf(buf, "target='%s' ", def->srvrecords[i].target);
+ if (def->srvrecords[i].port)
+ virBufferAsprintf(buf, "port='%d' ", def->srvrecords[i].port);
+ if (def->srvrecords[i].priority)
+ virBufferAsprintf(buf, "priority='%d' ", def->srvrecords[i].priority);
+ if (def->srvrecords[i].weight)
+ virBufferAsprintf(buf, "weight='%d' ", def->srvrecords[i].weight);
+
+ virBufferAsprintf(buf, "/>\n");
+ }
+ }
+
if (def->nhosts) {
int ii, j;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 869085e..5f05a3a 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -24,6 +24,8 @@
#ifndef __NETWORK_CONF_H__
# define __NETWORK_CONF_H__
+#define DNS_RECORD_LENGTH_SRV (512 - 30) /* Limit minus overhead as mentioned in RFC-2782 */
+
# include <libxml/parser.h>
# include <libxml/tree.h>
# include <libxml/xpath.h>
@@ -67,6 +69,18 @@ struct _virNetworkDNSTxtRecordsDef {
char *value;
};
+typedef struct _virNetworkDNSSrvRecordsDef virNetworkDNSSrvRecordsDef;
+typedef virNetworkDNSSrvRecordsDef *virNetworkDNSSrvRecordsDefPtr;
+struct _virNetworkDNSSrvRecordsDef {
+ char *domain;
+ char *service;
+ char *protocol;
+ char *target;
+ int port;
+ int priority;
+ int weight;
+};
+
struct _virNetworkDNSHostsDef {
virSocketAddr ip;
int nnames;
@@ -80,6 +94,8 @@ struct _virNetworkDNSDef {
virNetworkDNSTxtRecordsDefPtr txtrecords;
unsigned int nhosts;
virNetworkDNSHostsDefPtr hosts;
+ unsigned int nsrvrecords;
+ virNetworkDNSSrvRecordsDefPtr srvrecords;
};
typedef struct _virNetworkDNSDef *virNetworkDNSDefPtr;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c90db63..f4d952f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -559,6 +559,49 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
virCommandAddArgPair(cmd, "--txt-record", record);
VIR_FREE(record);
}
+
+ for (i = 0; i < dns->nsrvrecords; i++) {
+ char *record = NULL;
+ char *recordPort = NULL;
+ char *recordPriority = NULL;
+ char *recordWeight = NULL;
+
+ if (dns->srvrecords[i].service && dns->srvrecords[i].protocol) {
+ if (dns->srvrecords[i].port) {
+ if (virAsprintf(&recordPort, "%d", dns->srvrecords[i].port) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ if (dns->srvrecords[i].priority) {
+ if (virAsprintf(&recordPriority, "%d", dns->srvrecords[i].priority) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ if (dns->srvrecords[i].weight) {
+ if (virAsprintf(&recordWeight, "%d", dns->srvrecords[i].weight) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ if (virAsprintf(&record, "%s.%s.%s,%s,%s,%s,%s",
+ dns->srvrecords[i].service,
+ dns->srvrecords[i].protocol,
+ dns->srvrecords[i].domain ? dns->srvrecords[i].domain : "",
+ dns->srvrecords[i].target ? dns->srvrecords[i].target : "",
+ recordPort ? recordPort : "",
+ recordPriority ? recordPriority : "",
+ recordWeight ? recordWeight : "") < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ virCommandAddArgPair(cmd, "--srv-host", record);
+ VIR_FREE(record);
+ }
+ }
}
/*
diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
new file mode 100644
index 0000000..174f751
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
@@ -0,0 +1 @@
+/usr/sbin/dnsmasq --strict-order --bind-interfaces --conf-file= --except-interface lo --srv-host=name.tcp.,,,, --listen-address 192.168.122.1 --listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 --listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
\ No newline at end of file
diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.xml b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.xml
new file mode 100644
index 0000000..e9b7680
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.xml
@@ -0,0 +1,26 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <dns>
+ <srv service='name' protocol='tcp' />
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+ </dhcp>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
new file mode 100644
index 0000000..2ea9809
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
@@ -0,0 +1 @@
+/usr/sbin/dnsmasq --strict-order --bind-interfaces --conf-file= --except-interface lo --srv-host=name.tcp.test-domain-name,.,1024,10,10 --listen-address 192.168.122.1 --listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 --listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 --dhcp-range 192.168.122.2,192.168.122.254 --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases --dhcp-lease-max=253 --dhcp-no-override --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
\ No newline at end of file
diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.xml b/tests/networkxml2argvdata/nat-network-dns-srv-record.xml
new file mode 100644
index 0000000..4be85b5
--- /dev/null
+++ b/tests/networkxml2argvdata/nat-network-dns-srv-record.xml
@@ -0,0 +1,26 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <dns>
+ <srv service='name' protocol='tcp' domain='test-domain-name' target='.' port='1024' priority='10' weight='10' />
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+ </dhcp>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c
index 4a11d6f..2dd9b7f 100644
--- a/tests/networkxml2argvtest.c
+++ b/tests/networkxml2argvtest.c
@@ -120,6 +120,8 @@ mymain(void)
DO_TEST("netboot-network");
DO_TEST("netboot-proxy-network");
DO_TEST("nat-network-dns-txt-record");
+ DO_TEST("nat-network-dns-srv-record");
+ DO_TEST("nat-network-dns-srv-record-minimal");
DO_TEST("nat-network-dns-hosts");
return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
diff --git a/tests/networkxml2xmlin/nat-network-dns-srv-record-minimal.xml b/tests/networkxml2xmlin/nat-network-dns-srv-record-minimal.xml
new file mode 100644
index 0000000..e9b7680
--- /dev/null
+++ b/tests/networkxml2xmlin/nat-network-dns-srv-record-minimal.xml
@@ -0,0 +1,26 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <dns>
+ <srv service='name' protocol='tcp' />
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+ </dhcp>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2xmlin/nat-network-dns-srv-record.xml b/tests/networkxml2xmlin/nat-network-dns-srv-record.xml
new file mode 100644
index 0000000..4be85b5
--- /dev/null
+++ b/tests/networkxml2xmlin/nat-network-dns-srv-record.xml
@@ -0,0 +1,26 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <dns>
+ <srv service='name' protocol='tcp' domain='test-domain-name' target='.' port='1024' priority='10' weight='10' />
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+ </dhcp>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2xmlout/nat-network-dns-srv-record-minimal.xml b/tests/networkxml2xmlout/nat-network-dns-srv-record-minimal.xml
new file mode 100644
index 0000000..e9b7680
--- /dev/null
+++ b/tests/networkxml2xmlout/nat-network-dns-srv-record-minimal.xml
@@ -0,0 +1,26 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <dns>
+ <srv service='name' protocol='tcp' />
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+ </dhcp>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2xmlout/nat-network-dns-srv-record.xml b/tests/networkxml2xmlout/nat-network-dns-srv-record.xml
new file mode 100644
index 0000000..4be85b5
--- /dev/null
+++ b/tests/networkxml2xmlout/nat-network-dns-srv-record.xml
@@ -0,0 +1,26 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'>
+ <interface dev='eth1'/>
+ </forward>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <dns>
+ <srv service='name' protocol='tcp' domain='test-domain-name' target='.' port='1024' priority='10' weight='10' />
+ </dns>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
+ </dhcp>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 5cdbedb..b9f6546 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -87,6 +87,8 @@ mymain(void)
DO_TEST("netboot-network");
DO_TEST("netboot-proxy-network");
DO_TEST("nat-network-dns-txt-record");
+ DO_TEST("nat-network-dns-srv-record");
+ DO_TEST("nat-network-dns-srv-record-minimal");
DO_TEST("nat-network-dns-hosts");
DO_TEST("8021Qbh-net");
DO_TEST("direct-net");
--
1.7.4.4
13 years, 4 months
[libvirt] [PATCH] qemu: support event_idx parameter for virtio disk and net devices
by Laine Stump
In some versions of qemu, both virtio-blk-pci and virtio-net-pci
devices can have an event_idx setting that determines some details of
event processing. When it is enabled, it "reduces the number of
interrupts and exits for the guest". qemu will automatically enable
this feature when it is available, but there may be cases where this
new feature could actually make performance worse (NB: no such case
has been found so far).
As a safety switch in case such a situation is encountered in the
field, this patch adds a new attribute "event_idx" to the <driver>
element of both disk and interface devices. event_idx can be set to
"on" (to force event_idx on in case qemu has it disabled by default)
or "off" (for force event_idx off). In the case that event_idx support
isn't present in qemu, the attribute is ignored (this on the advice of
the qemu developer).
docs/formatdomain.html.in: document the new flag (marking it as
"don't mess with this!"
docs/schemas/domain.rng: add event_idx in appropriate places
src/conf/domain_conf.[ch]: add event_idx to parser and formatter
src/libvirt_private.syms: export
virDomainVirtioEventIdx(From|To)String
src/qemu/qemu_capabilities.[ch]: detect and report event_idx in
disk/net
src/qemu/qemu_command.c: add event_idx parameter to qemu commandline
when appropriate.
tests/qemuxml2argvdata/qemuxml2argv-event_idx.args,
tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml,
tests/qemuxml2argvtest.c,
tests/qemuxml2xmltest.c: test cases for event_idx.
---
docs/formatdomain.html.in | 31 ++++++++++-
docs/schemas/domain.rng | 14 +++++
src/conf/domain_conf.c | 47 ++++++++++++++++-
src/conf/domain_conf.h | 11 ++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_capabilities.c | 6 ++
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 13 ++++-
tests/qemuxml2argvdata/qemuxml2argv-event_idx.args | 11 ++++
tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml | 57 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 5 ++
tests/qemuxml2xmltest.c | 1 +
12 files changed, 196 insertions(+), 4 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-event_idx.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 7d2ba8a..f46771d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -904,7 +904,7 @@
</disk>
...
<disk type='network'>
- <driver name="qemu" type="raw" io="threads" ioeventfd="on"/>
+ <driver name="qemu" type="raw" io="threads" ioeventfd="on" event_idx="off"/>
<source protocol="sheepdog" name="image_name">
<host name="hostname" port="7000"/>
</source>
@@ -1004,6 +1004,19 @@
<b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b>
</li>
+ <li>
+ The optional <code>event_idx</code> attribute controls
+ some aspects of device event processing. The value can be
+ either 'on' or 'off' - if it is on, it will reduce the
+ number of interupts and exits for the guest. The default
+ is determined by QEMU; usually if the feature is
+ supported, default is on. In case there is a situation
+ where this behavior is suboptimal, this attribute provides
+ a way to force the feature off.
+ <span class="since">Since 0.9.5 (QEMU and KVM only)</span>
+ <b>In general you should leave this option alone, unless you
+ are very certain you know what you are doing.</b>
+ </li>
</ul>
</dd>
<dt><code>boot</code></dt>
@@ -1850,7 +1863,7 @@ qemu-kvm -net nic,model=? /dev/null
<source network='default'/>
<target dev='vnet1'/>
<model type='virtio'/>
- <b><driver name='vhost' txmode='iothread' ioeventfd='on'/></b>
+ <b><driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off'/></b>
</interface>
</devices>
...</pre>
@@ -1917,6 +1930,20 @@ qemu-kvm -net nic,model=? /dev/null
<b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b>
</dd>
+ <dt><code>event_idx</code></dt>
+ <dd>
+ The <code>event_idx</code> attribute controls some aspects of
+ device event processing. The value can be either 'on' or 'off'
+ - if it is on, it will reduce the number of interupts and
+ exits for the guest. The default is determined by QEMU;
+ usually if the feature is supported, default is on. In case
+ there is a situation where this behavior is suboptimal, this
+ attribute provides a way to force the feature off.
+ <span class="since">Since 0.9.5 (QEMU and KVM only)</span><br/><br/>
+
+ <b>In general you should leave this option alone, unless you
+ are very certain you know what you are doing.</b>
+ </dd>
</dl>
<h5><a name="elementsNICSTargetOverride">Overriding the target element</a></h5>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 6ccbeed..dd8c41a 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -807,6 +807,9 @@
<optional>
<ref name="ioeventfd"/>
</optional>
+ <optional>
+ <ref name="event_idx"/>
+ </optional>
<empty/>
</element>
</define>
@@ -854,6 +857,14 @@
</choice>
</attribute>
</define>
+ <define name="event_idx">
+ <attribute name="event_idx">
+ <choice>
+ <value>on</value>
+ <value>off</value>
+ </choice>
+ </attribute>
+ </define>
<define name="controller">
<element name="controller">
<choice>
@@ -1165,6 +1176,9 @@
<optional>
<ref name="ioeventfd"/>
</optional>
+ <optional>
+ <ref name="event_idx"/>
+ </optional>
<empty/>
</element>
</optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 010ce57..ce1f3c5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -182,6 +182,10 @@ VIR_ENUM_IMPL(virDomainIoEventFd, VIR_DOMAIN_IO_EVENT_FD_LAST,
"on",
"off")
+VIR_ENUM_IMPL(virDomainVirtioEventIdx, VIR_DOMAIN_VIRTIO_EVENT_IDX_LAST,
+ "default",
+ "on",
+ "off")
VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
"ide",
@@ -2081,6 +2085,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
char *error_policy = NULL;
char *iotag = NULL;
char *ioeventfd = NULL;
+ char *event_idx = NULL;
char *devaddr = NULL;
virStorageEncryptionPtr encryption = NULL;
char *serial = NULL;
@@ -2197,6 +2202,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
error_policy = virXMLPropString(cur, "error_policy");
iotag = virXMLPropString(cur, "io");
ioeventfd = virXMLPropString(cur, "ioeventfd");
+ event_idx = virXMLPropString(cur, "event_idx");
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
def->readonly = 1;
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
@@ -2351,6 +2357,24 @@ virDomainDiskDefParseXML(virCapsPtr caps,
def->ioeventfd=i;
}
+ if (event_idx) {
+ if (def->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("disk event_idx mode supported "
+ "only for virtio bus"));
+ goto error;
+ }
+
+ int idx;
+ if ((idx = virDomainVirtioEventIdxTypeFromString(event_idx)) <= 0) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown disk event_idx mode '%s'"),
+ event_idx);
+ goto error;
+ }
+ def->event_idx = idx;
+ }
+
if (devaddr) {
if (virDomainParseLegacyDeviceAddress(devaddr,
&def->info.addr.pci) < 0) {
@@ -2414,6 +2438,7 @@ cleanup:
VIR_FREE(error_policy);
VIR_FREE(iotag);
VIR_FREE(ioeventfd);
+ VIR_FREE(event_idx);
VIR_FREE(devaddr);
VIR_FREE(serial);
virStorageEncryptionFree(encryption);
@@ -2744,6 +2769,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *backend = NULL;
char *txmode = NULL;
char *ioeventfd = NULL;
+ char *event_idx = NULL;
char *filter = NULL;
char *internal = NULL;
char *devaddr = NULL;
@@ -2835,6 +2861,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
backend = virXMLPropString(cur, "name");
txmode = virXMLPropString(cur, "txmode");
ioeventfd = virXMLPropString(cur, "ioeventfd");
+ event_idx = virXMLPropString(cur, "event_idx");
} else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
filter = virXMLPropString(cur, "filter");
VIR_FREE(filterparams);
@@ -3075,6 +3102,16 @@ virDomainNetDefParseXML(virCapsPtr caps,
}
def->driver.virtio.ioeventfd = i;
}
+ if (event_idx) {
+ int idx;
+ if ((idx = virDomainVirtioEventIdxTypeFromString(event_idx)) <= 0) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown interface event_idx mode '%s'"),
+ event_idx);
+ goto error;
+ }
+ def->driver.virtio.event_idx = idx;
+ }
}
if (filter != NULL) {
@@ -3118,6 +3155,7 @@ cleanup:
VIR_FREE(backend);
VIR_FREE(txmode);
VIR_FREE(ioeventfd);
+ VIR_FREE(event_idx);
VIR_FREE(filter);
VIR_FREE(type);
VIR_FREE(internal);
@@ -8576,6 +8614,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy);
const char *iomode = virDomainDiskIoTypeToString(def->iomode);
const char *ioeventfd = virDomainIoEventFdTypeToString(def->ioeventfd);
+ const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx);
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -8608,7 +8647,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
type, device);
if (def->driverName || def->driverType || def->cachemode ||
- def->ioeventfd) {
+ def->ioeventfd || def->event_idx) {
virBufferAsprintf(buf, " <driver");
if (def->driverName)
virBufferAsprintf(buf, " name='%s'", def->driverName);
@@ -8622,6 +8661,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " io='%s'", iomode);
if (def->ioeventfd)
virBufferAsprintf(buf, " ioeventfd='%s'", ioeventfd);
+ if (def->event_idx)
+ virBufferAsprintf(buf, " event_idx='%s'", event_idx);
virBufferAsprintf(buf, "/>\n");
}
@@ -8996,6 +9037,10 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " ioeventfd='%s'",
virDomainIoEventFdTypeToString(def->driver.virtio.ioeventfd));
}
+ if (def->driver.virtio.event_idx) {
+ virBufferAsprintf(buf, " event_idx='%s'",
+ virDomainVirtioEventIdxTypeToString(def->driver.virtio.event_idx));
+ }
virBufferAddLit(buf, "/>\n");
}
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1d5af95..2cc9b06 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -209,6 +209,14 @@ enum virDomainIoEventFd {
VIR_DOMAIN_IO_EVENT_FD_LAST
};
+enum virDomainVirtioEventIdx {
+ VIR_DOMAIN_VIRTIO_EVENT_IDX_DEFAULT = 0,
+ VIR_DOMAIN_VIRTIO_EVENT_IDX_ON,
+ VIR_DOMAIN_VIRTIO_EVENT_IDX_OFF,
+
+ VIR_DOMAIN_VIRTIO_EVENT_IDX_LAST
+};
+
/* Stores the virtual disk configuration */
typedef struct _virDomainDiskDef virDomainDiskDef;
typedef virDomainDiskDef *virDomainDiskDefPtr;
@@ -229,6 +237,7 @@ struct _virDomainDiskDef {
int bootIndex;
int iomode;
int ioeventfd;
+ int event_idx;
unsigned int readonly : 1;
unsigned int shared : 1;
virDomainDeviceInfo info;
@@ -377,6 +386,7 @@ struct _virDomainNetDef {
enum virDomainNetBackendType name; /* which driver backend to use */
enum virDomainNetVirtioTxModeType txmode;
enum virDomainIoEventFd ioeventfd;
+ enum virDomainVirtioEventIdx event_idx;
} virtio;
} driver;
union {
@@ -1661,6 +1671,7 @@ VIR_ENUM_DECL(virDomainDiskErrorPolicy)
VIR_ENUM_DECL(virDomainDiskProtocol)
VIR_ENUM_DECL(virDomainDiskIo)
VIR_ENUM_DECL(virDomainIoEventFd)
+VIR_ENUM_DECL(virDomainVirtioEventIdx)
VIR_ENUM_DECL(virDomainController)
VIR_ENUM_DECL(virDomainControllerModel)
VIR_ENUM_DECL(virDomainFS)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 64b91ee..4286fbd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -414,6 +414,8 @@ virDomainVideoDefaultRAM;
virDomainVideoDefaultType;
virDomainVideoTypeFromString;
virDomainVideoTypeToString;
+virDomainVirtioEventIdxTypeFromString;
+virDomainVirtioEventIdxTypeToString;
virDomainVirtTypeToString;
virDomainWatchdogActionTypeFromString;
virDomainWatchdogActionTypeToString;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 3f36212..f665de4 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -123,6 +123,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"pci-multifunction", /* 60 */
"virtio-blk-pci.ioeventfd",
"sga",
+ "virtio-blk-pci.event_idx",
+ "virtio-net-pci.event_idx",
);
struct qemu_feature_flags {
@@ -1215,6 +1217,10 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags)
qemuCapsSet(flags, QEMU_CAPS_VIRTIO_IOEVENTFD);
if (strstr(str, "name \"sga\""))
qemuCapsSet(flags, QEMU_CAPS_SGA);
+ if (strstr(str, "virtio-blk-pci.event_idx"))
+ qemuCapsSet(flags, QEMU_CAPS_VIRTIO_BLK_EVENT_IDX);
+ if (strstr(str, "virtio-net-pci.event_idx"))
+ qemuCapsSet(flags, QEMU_CAPS_VIRTIO_NET_EVENT_IDX);
return 0;
}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index d251262..13af0b9 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -98,6 +98,8 @@ enum qemuCapsFlags {
QEMU_CAPS_PCI_MULTIFUNCTION = 60, /* -device multifunction=on|off */
QEMU_CAPS_VIRTIO_IOEVENTFD = 61, /* IOeventFD feature: virtio-{net|blk}-pci.ioeventfd=on/off */
QEMU_CAPS_SGA = 62, /* Serial Graphics Adapter */
+ QEMU_CAPS_VIRTIO_BLK_EVENT_IDX = 63, /* virtio-blk-pci.event_idx */
+ QEMU_CAPS_VIRTIO_NET_EVENT_IDX = 64, /* virtio-net-pci.event_idx */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2a48826..dbfc7d9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1585,6 +1585,11 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
case VIR_DOMAIN_DISK_BUS_VIRTIO:
virBufferAddLit(&opt, "virtio-blk-pci");
qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps);
+ if (disk->event_idx &&
+ qemuCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_EVENT_IDX)) {
+ virBufferAsprintf(&opt, ",event_idx=%s",
+ virDomainVirtioEventIdxTypeToString(disk->event_idx));
+ }
qemuBuildDeviceAddressStr(&opt, &disk->info, qemuCaps);
break;
case VIR_DOMAIN_DISK_BUS_USB:
@@ -1808,8 +1813,14 @@ qemuBuildNicDevStr(virDomainNetDefPtr net,
goto error;
}
}
- if (usingVirtio)
+ if (usingVirtio) {
qemuBuildIoEventFdStr(&buf, net->driver.virtio.ioeventfd, qemuCaps);
+ if (net->driver.virtio.event_idx &&
+ qemuCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EVENT_IDX)) {
+ virBufferAsprintf(&buf, ",event_idx=%s",
+ virDomainVirtioEventIdxTypeToString(net->driver.virtio.event_idx));
+ }
+ }
if (vlan == -1)
virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
else
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-event_idx.args b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.args
new file mode 100644
index 0000000..f6ebb60
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.args
@@ -0,0 +1,11 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc-0.13 -m 1024 -smp 1 -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi \
+-boot dc -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \
+-drive file=/var/lib/libvirt/images/f14.img,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,event_idx=on,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0 \
+-drive file=/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-device virtio-net-pci,event_idx=off,vlan=0,id=net0,mac=52:54:00:e5:48:58,bus=pci.0,addr=0x3 \
+-net user,vlan=0,name=hostnet0 -serial pty -usb -vnc 127.0.0.1:-809 -std-vga \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml
new file mode 100644
index 0000000..81f2200
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml
@@ -0,0 +1,57 @@
+<domain type='qemu'>
+ <name>test</name>
+ <uuid>bba65c0e-c049-934f-b6aa-4e2c0582acdf</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-0.13'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='hd'/>
+ <bootmenu enable='yes'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' event_idx='on'/>
+ <source file='/var/lib/libvirt/images/f14.img'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <controller type='virtio-serial' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
+ </controller>
+ <controller type='ide' index='0'/>
+ <interface type='user'>
+ <mac address='52:54:00:e5:48:58'/>
+ <model type='virtio'/>
+ <driver name='vhost' event_idx='off'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='5091' autoport='no' listen='127.0.0.1'>
+ <listen type='address' address='127.0.0.1'/>
+ </graphics>
+ <video>
+ <model type='vga' vram='9216' heads='1'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </video>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 434264a..6e8da5e 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -359,6 +359,11 @@ mymain(void)
DO_TEST("disk-ioeventfd", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_VIRTIO_IOEVENTFD,
QEMU_CAPS_VIRTIO_TX_ALG, QEMU_CAPS_DEVICE);
+ DO_TEST("event_idx", false,
+ QEMU_CAPS_DRIVE,
+ QEMU_CAPS_VIRTIO_BLK_EVENT_IDX,
+ QEMU_CAPS_VIRTIO_NET_EVENT_IDX,
+ QEMU_CAPS_DEVICE);
DO_TEST("graphics-vnc", false, NONE);
DO_TEST("graphics-vnc-socket", false, NONE);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index c74f96c..4e109d5 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -187,6 +187,7 @@ mymain(void)
DO_TEST("smp");
DO_TEST("lease");
+ DO_TEST("event_idx");
/* These tests generate different XML */
DO_TEST_DIFFERENT("balloon-device-auto");
--
1.7.3.4
13 years, 4 months
[libvirt] [libvirt-test-API][PATCH] fix the problem of return None value of self.conn
by Wayne Sun
---
lib/connectAPI.py | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/connectAPI.py b/lib/connectAPI.py
index 702a088..cfa4fea 100644
--- a/lib/connectAPI.py
+++ b/lib/connectAPI.py
@@ -44,7 +44,7 @@ class ConnectAPI(object):
def open(self, uri):
try:
- conn = libvirt.open(uri)
+ self.conn = libvirt.open(uri)
return self.conn
except libvirt.libvirtError, e:
message = e.get_error_message()
@@ -53,7 +53,7 @@ class ConnectAPI(object):
def open_read_only(self, uri):
try:
- conn = libvirt.openReadOnly(uri)
+ self.conn = libvirt.openReadOnly(uri)
return self.conn
except libvirt.libvirtError, e:
message = e.get_error_message()
@@ -62,7 +62,7 @@ class ConnectAPI(object):
def openAuth(self, uri, auth, flags = 0):
try:
- conn = libvirt.openAuth(uri, auth, flags)
+ self.conn = libvirt.openAuth(uri, auth, flags)
return self.conn
except libvirt.libvirtError, e:
message = e.get_error_message()
--
1.7.1
13 years, 4 months
[libvirt] [PATCH] maint: ignore generated file
by Eric Blake
* .gitignore: Ignore qemu-sanlock.conf.
---
I backported the latest sanlock-devel and netcf-devel from rawhide
back to F14, so that I can test more code without upgrading distros,
and noticed this file in 'git status'.
Pushing under the trivial rule.
.gitignore | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index 60220ad..e8b2dbf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,6 +54,7 @@
/proxy/
/python/generator.py.stamp
/src/libvirt_iohelper
+/src/locking/qemu-sanlock.conf
/src/remote/*_client_bodies.h
/src/remote/*_protocol.[ch]
/src/rpc/virnetprotocol.[ch]
--
1.7.4.4
13 years, 4 months
[libvirt] [PATCH v2] Ensure client streams are closed when marking a client for close
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
NB, previous patch was borked due to bad rebase
Every active stream results in a reference being held on the
virNetServerClientPtr object. This meant that if a client quit
with any streams active, although all I/O was stopped the
virNetServerClientPtr object would leak. This causes libvirtd
to leak any file handles associated with open streams when a
client quit
To fix this, when we call virNetServerClientClose there is a
callback invoked which lets the daemon release the streams
and thus the extra references
* daemon/remote.c: Add a hook to close all streams
* daemon/stream.c, daemon/stream.h: Add API for releasing
all streams
* src/rpc/virnetserverclient.c, src/rpc/virnetserverclient.h:
Allow registration of a hook to trigger when closing client
---
daemon/remote.c | 11 ++++++++++-
daemon/stream.c | 38 ++++++++++++++++++++++++++++++++------
daemon/stream.h | 3 +++
src/rpc/virnetserverclient.c | 21 +++++++++++++++++++++
src/rpc/virnetserverclient.h | 5 +++++
5 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 939044c..0f088c6 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -439,6 +439,13 @@ static void remoteClientFreeFunc(void *data)
}
+static void remoteClientCloseFunc(virNetServerClientPtr client)
+{
+ struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
+
+ daemonRemoveAllClientStreams(priv->streams);
+}
+
int remoteClientInitHook(virNetServerPtr srv ATTRIBUTE_UNUSED,
virNetServerClientPtr client)
@@ -460,7 +467,9 @@ int remoteClientInitHook(virNetServerPtr srv ATTRIBUTE_UNUSED,
for (i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i++)
priv->domainEventCallbackID[i] = -1;
- virNetServerClientSetPrivateData(client, priv, remoteClientFreeFunc);
+ virNetServerClientSetPrivateData(client, priv,
+ remoteClientFreeFunc);
+ virNetServerClientSetCloseHook(client, remoteClientCloseFunc);
return 0;
}
diff --git a/daemon/stream.c b/daemon/stream.c
index 4a8f1ee..c6865a8 100644
--- a/daemon/stream.c
+++ b/daemon/stream.c
@@ -334,13 +334,17 @@ int daemonFreeClientStream(virNetServerClientPtr client,
msg = stream->rx;
while (msg) {
virNetMessagePtr tmp = msg->next;
- /* Send a dummy reply to free up 'msg' & unblock client rx */
- memset(msg, 0, sizeof(*msg));
- msg->header.type = VIR_NET_REPLY;
- if (virNetServerClientSendMessage(client, msg) < 0) {
- virNetServerClientImmediateClose(client);
+ if (client) {
+ /* Send a dummy reply to free up 'msg' & unblock client rx */
+ memset(msg, 0, sizeof(*msg));
+ msg->header.type = VIR_NET_REPLY;
+ if (virNetServerClientSendMessage(client, msg) < 0) {
+ virNetServerClientImmediateClose(client);
+ virNetMessageFree(msg);
+ ret = -1;
+ }
+ } else {
virNetMessageFree(msg);
- ret = -1;
}
msg = tmp;
}
@@ -441,6 +445,28 @@ daemonRemoveClientStream(virNetServerClientPtr client,
}
+void
+daemonRemoveAllClientStreams(daemonClientStream *stream)
+{
+ daemonClientStream *tmp;
+
+ VIR_DEBUG("stream=%p", stream);
+
+ while (stream) {
+ tmp = stream->next;
+
+ if (!stream->closed) {
+ virStreamEventRemoveCallback(stream->st);
+ virStreamAbort(stream->st);
+ }
+
+ daemonFreeClientStream(NULL, stream);
+
+ VIR_DEBUG("next stream=%p", stream);
+ stream = tmp;
+ }
+}
+
/*
* Returns:
* -1 if fatal error occurred
diff --git a/daemon/stream.h b/daemon/stream.h
index 626ae60..7c2d8dc 100644
--- a/daemon/stream.h
+++ b/daemon/stream.h
@@ -45,4 +45,7 @@ int
daemonRemoveClientStream(virNetServerClientPtr client,
daemonClientStream *stream);
+void
+daemonRemoveAllClientStreams(daemonClientStream *stream);
+
#endif /* __LIBVIRTD_STREAM_H__ */
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index e246fa5..a73b06d 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -97,6 +97,7 @@ struct _virNetServerClient
void *privateData;
virNetServerClientFreeFunc privateDataFreeFunc;
+ virNetServerClientCloseFunc privateDataCloseFunc;
};
@@ -492,6 +493,15 @@ void *virNetServerClientGetPrivateData(virNetServerClientPtr client)
}
+void virNetServerClientSetCloseHook(virNetServerClientPtr client,
+ virNetServerClientCloseFunc cf)
+{
+ virNetServerClientLock(client);
+ client->privateDataCloseFunc = cf;
+ virNetServerClientUnlock(client);
+}
+
+
void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque)
@@ -560,6 +570,8 @@ void virNetServerClientFree(virNetServerClientPtr client)
*/
void virNetServerClientClose(virNetServerClientPtr client)
{
+ virNetServerClientCloseFunc cf;
+
virNetServerClientLock(client);
VIR_DEBUG("client=%p refs=%d", client, client->refs);
if (!client->sock) {
@@ -567,6 +579,15 @@ void virNetServerClientClose(virNetServerClientPtr client)
return;
}
+ if (client->privateDataCloseFunc) {
+ cf = client->privateDataCloseFunc;
+ client->refs++;
+ virNetServerClientUnlock(client);
+ (cf)(client);
+ virNetServerClientLock(client);
+ client->refs--;
+ }
+
/* Do now, even though we don't close the socket
* until end, to ensure we don't get invoked
* again due to tls shutdown */
diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h
index 3d2e1fb..bedb179 100644
--- a/src/rpc/virnetserverclient.h
+++ b/src/rpc/virnetserverclient.h
@@ -82,6 +82,11 @@ void virNetServerClientSetPrivateData(virNetServerClientPtr client,
virNetServerClientFreeFunc ff);
void *virNetServerClientGetPrivateData(virNetServerClientPtr client);
+typedef void (*virNetServerClientCloseFunc)(virNetServerClientPtr client);
+
+void virNetServerClientSetCloseHook(virNetServerClientPtr client,
+ virNetServerClientCloseFunc cf);
+
void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque);
--
1.7.6
13 years, 4 months