[libvirt] [PATCHv3 00/11] Multiple TX queue support
by Michal Privoznik
Fixed version with Laine's comments worked in [1].
Patches 2, 3 and 5 has been ACKed already. BTW, patch 4 is really a different
to patch 3. The only thing they share is a commit message body.
Kernel and subsequently QEMU learned multiple transmit queues a while ago. The
feature has a nice advantage, it allows a single guest to transmit multiple
flows of network data using multiple CPUs simultaneously which increase traffic
bandwidth. A lot.
The documentation how to use this is available at [2] or [3].
1: https://www.redhat.com/archives/libvir-list/2013-May/msg00943.html
2: https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/tree/Docu...
3: http://git.qemu.org/?p=qemu.git;a=blob;f=qemu-options.hx;hb=HEAD#l1363
Michal Privoznik (11):
Introduce /domain/devices/interface/driver/@queues attribute
qemu: Move interface cmd line construction into a separate function
qemu: Make qemuMonitorAddNetdev to pass multiple FDs
qemu: Make qemuMonitorAddHostNetwork to pass multiple FDs
qemu: Adapt command line generation to multiqueue net
util: Learn virNetDevTapCreate multiqueue network
qemu: Allow multiple vhost-net openings
qemu: Rework qemuNetworkIfaceConnect
qemu: Adapt qemuDomainAttachNetDevice to multiqueue net
qemu: Adapt qemuBuildInterfaceCommandLine to to multiqueue net
qemu: Enable multiqueue network
docs/formatdomain.html.in | 12 +-
docs/schemas/domaincommon.rng | 5 +
src/conf/domain_conf.c | 15 +
src/conf/domain_conf.h | 1 +
src/network/bridge_driver.c | 2 +-
src/qemu/qemu_command.c | 447 +++++++++++++--------
src/qemu/qemu_command.h | 13 +-
src/qemu/qemu_hotplug.c | 103 +++--
src/qemu/qemu_monitor.c | 78 ++--
src/qemu/qemu_monitor.h | 8 +-
src/uml/uml_conf.c | 5 +-
src/util/virnetdevtap.c | 113 +++---
src/util/virnetdevtap.h | 2 +
.../qemuxml2argvdata/qemuxml2argv-vhost_queues.xml | 51 +++
tests/qemuxml2xmltest.c | 1 +
15 files changed, 568 insertions(+), 288 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-vhost_queues.xml
--
1.8.2.1
11 years, 6 months
[libvirt] [PATCH v2] openvzDomainSetNetwork: use virCommand
by Michal Privoznik
Currently, the openvzDomainSetNetwork function constructs an
array of strings representing a command line for VZCTL binary.
This is a overkill since our virCommand APIs can cover all the
functionality. Moreover, the function is not following our
structure where return value is set to -1 initially, and after
all operations succeeded then it is set to zero.
---
src/openvz/openvz_driver.c | 80 +++++++++++-----------------------------------
1 file changed, 19 insertions(+), 61 deletions(-)
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 129e328..d46baab 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -88,15 +88,6 @@ static void openvzDriverUnlock(struct openvz_driver *driver)
struct openvz_driver ovz_driver;
-static void cmdExecFree(const char *cmdExec[])
-{
- int i=-1;
- while (cmdExec[++i]) {
- VIR_FREE(cmdExec[i]);
- }
-}
-
-
static int
openvzDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
@@ -827,22 +818,13 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
virDomainNetDefPtr net,
virBufferPtr configBuf)
{
- int rc = 0, narg;
- const char *prog[OPENVZ_MAX_ARG];
+ int rc = -1;
char macaddr[VIR_MAC_STRING_BUFLEN];
virMacAddr host_mac;
char host_macaddr[VIR_MAC_STRING_BUFLEN];
struct openvz_driver *driver = conn->privateData;
char *opt = NULL;
-
-#define ADD_ARG_LIT(thisarg) \
- do { \
- if (narg >= OPENVZ_MAX_ARG) \
- goto no_memory; \
- if ((prog[narg++] = strdup(thisarg)) == NULL) \
- goto no_memory; \
- } while (0)
-
+ virCommandPtr cmd = NULL;
if (net == NULL)
return 0;
@@ -852,18 +834,11 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
return -1;
}
- for (narg = 0; narg < OPENVZ_MAX_ARG; narg++)
- prog[narg] = NULL;
+ if (net->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
+ net->type != VIR_DOMAIN_NET_TYPE_ETHERNET)
+ return 0;
- narg = 0;
-
- if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
- net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
- ADD_ARG_LIT(VZCTL);
- ADD_ARG_LIT("--quiet");
- ADD_ARG_LIT("set");
- ADD_ARG_LIT(vpsid);
- }
+ cmd = virCommandNewArgList(VZCTL, "--quiet", "set", vpsid, NULL);
virMacAddrFormat(&net->mac, macaddr);
virDomainNetGenerateMAC(driver->xmlopt, &host_mac);
@@ -875,9 +850,6 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
virBuffer buf = VIR_BUFFER_INITIALIZER;
int veid = openvzGetVEID(vpsid);
- /* --netif_add ifname[,mac,host_ifname,host_mac] */
- ADD_ARG_LIT("--netif_add") ;
-
/* if user doesn't specify guest interface name,
* then we need to generate it */
if (net->data.ethernet.dev == NULL) {
@@ -885,8 +857,7 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
if (net->data.ethernet.dev == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not generate eth name for container"));
- rc = -1;
- goto exit;
+ goto cleanup;
}
}
@@ -897,8 +868,7 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
if (net->ifname == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not generate veth name"));
- rc = -1;
- goto exit;
+ goto cleaup;
}
}
@@ -919,40 +889,28 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
}
}
- if (!(opt = virBufferContentAndReset(&buf)))
- goto no_memory;
+ if (!(opt = virBufferContentAndReset(&buf))) {
+ virReportOOMError();
+ goto cleanup;
+ }
- ADD_ARG_LIT(opt) ;
+ /* --netif_add ifname[,mac,host_ifname,host_mac] */
+ virCommandAddArgList(cmd, "--netif_add", opt, NULL);
VIR_FREE(opt);
} else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
net->data.ethernet.ipaddr != NULL) {
/* --ipadd ip */
- ADD_ARG_LIT("--ipadd") ;
- ADD_ARG_LIT(net->data.ethernet.ipaddr) ;
+ virCommandAddArgList(cmd, "--ipadd", net->data.ethernet.ipaddr, NULL);
}
/* TODO: processing NAT and physical device */
- if (prog[0] != NULL) {
- ADD_ARG_LIT("--save");
- if (virRun(prog, NULL) < 0) {
- rc = -1;
- goto exit;
- }
- }
+ virCommandAddArg(cmd, "--save");
+ ret = virCommandRun(cmd, NULL);
- exit:
- cmdExecFree(prog);
+ cleanup:
+ virCommandFree(cmd);
return rc;
-
- no_memory:
- VIR_FREE(opt);
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not put argument to %s"), VZCTL);
- cmdExecFree(prog);
- return -1;
-
-#undef ADD_ARG_LIT
}
--
1.8.2.1
11 years, 6 months
[libvirt] [PATCH 0/2] qemu: Rework CD/DVD changing
by Michal Privoznik
The first patch is bare bug fix (without any bug reported though).
The second is again a bug fix, but not so easy to spot. Basically, when we
change a media, we should issue 'eject' first, then wait until the tray gets
open, after which we can finally issue 'change' command. Even for bare 'eject'
we ought to check status, shouldn't we?
Michal Privoznik (2):
qemu_monitor: Fix tray-open attribute in query-block
qemu_hotplug: Rework media changing process
src/qemu/qemu_hotplug.c | 51 +++++++++++++++++++++++++++++++++++++++++---
src/qemu/qemu_monitor_json.c | 2 +-
src/qemu/qemu_monitor_text.c | 6 +++---
3 files changed, 52 insertions(+), 7 deletions(-)
--
1.8.0.2
11 years, 6 months
[libvirt] two nasty races
by Eric Blake
I found root cause on two nasty races today, but ran out of time to
write the patches until next week.
1. We have a TOCTTOU race when moving processes between cgroups.
virCgroupMoveTask can fail if listing the threads in the parent group
picks up multiple threads, then one of those threads exits before we
then write to the emulator subgroup to relocate those threads; the chain
reaction from this failure is that the domain fails to start. qemu
spawns short-lived threads all the time (possibly due to glibc using
threads under the hood to implement aio as qemu first probes a disk
image); with a 3-second-delay hook script, I was able to hit this race
about 5% of the time when repeatedly starting multiple domains in
parallel. The fix should be ignoring any ESRCH failures when writing
during virCgroupAddTAskStrController, but I plan to test that before
posting my patch. Present at least since 0.10.2 (Fedora 18); probably
earlier (but I didn't check how far back).
2. We have a (rare) deadlock due to the use of a non-async-signal-safe
getpwuid_r in between fork and exec. I was extremely surprised when I
hit it in real life while trying to debug the first race; but sure
enough, the backtrace confirms that glibc grabs a mutex inside
getpwuid_r, and if some other thread in the parent process is
interrupted in the middle of getpwuid_r while we are forking a child in
our thread, then our child is hung; and since the parent depends on a
handshake with the child, the parent's worker thread was also hung. I
think the fix to this is to call getpwuid_r prior to fork, and change
virSetUIDGID to take the list of supplemental groups as a parameter
rather than trying to learn it on the fly. Again, something I plan to
test once I have the patch written. Present at least since commit
f42cf7cb (Dec 2010) with the introduction of virSetUIDGID, and probably
further back.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
11 years, 6 months
[libvirt] [PATCH] esx: Implement esxDomainSetMemoryFlags
by Matthias Bolte
---
src/esx/esx_driver.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index b55ef45..3962bf1 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -2187,6 +2187,27 @@ esxDomainSetMemory(virDomainPtr domain, unsigned long memory)
+static int
+esxDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
+ unsigned int flags)
+{
+ if (flags != VIR_DOMAIN_MEM_CURRENT &&
+ flags != VIR_DOMAIN_MEM_LIVE &&
+ flags != (VIR_DOMAIN_MEM_CURRENT | VIR_DOMAIN_MEM_MAXIMUM) &&
+ flags != (VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM)) {
+ virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return -1;
+ }
+
+ if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
+ return esxDomainSetMaxMemory(domain, memory);
+ } else {
+ return esxDomainSetMemory(domain, memory);
+ }
+}
+
+
+
/*
* libvirt exposed virtual CPU usage in absolute time, ESX doesn't provide this
* information in this format. It exposes it in 20 seconds slots, but it's hard
@@ -5286,6 +5307,7 @@ static virDriver esxDriver = {
.domainGetMaxMemory = esxDomainGetMaxMemory, /* 0.7.0 */
.domainSetMaxMemory = esxDomainSetMaxMemory, /* 0.7.0 */
.domainSetMemory = esxDomainSetMemory, /* 0.7.0 */
+ .domainSetMemoryFlags = esxDomainSetMemoryFlags, /* 1.0.6 */
.domainSetMemoryParameters = esxDomainSetMemoryParameters, /* 0.8.6 */
.domainGetMemoryParameters = esxDomainGetMemoryParameters, /* 0.8.6 */
.domainGetInfo = esxDomainGetInfo, /* 0.7.0 */
--
1.7.9.5
11 years, 6 months
[libvirt] [PATCH] esx: Accept VIR_DOMAIN_AFFECT_CURRENT in addition to VIR_DOMAIN_AFFECT_LIVE
by Matthias Bolte
Basically autotranslate VIR_DOMAIN_AFFECT_CURRENT to VIR_DOMAIN_AFFECT_LIVE.
Modification impact is handled lax anyway. There is no distinction between
a live and a stored config in the VMware world. A strict modification impact
handling would require to check the virtual machine state each time and enforce
VIR_DOMAIN_AFFECT_LIVE-only for running and VIR_DOMAIN_AFFECT_CONFIG-only
for inactive domains. But that would be useless overhead.
---
src/esx/esx_driver.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index f53b9c4..85640ce 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -2531,7 +2531,7 @@ esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus,
esxVI_TaskInfoState taskInfoState;
char *taskInfoErrorMessage = NULL;
- if (flags != VIR_DOMAIN_AFFECT_LIVE) {
+ if (flags != VIR_DOMAIN_AFFECT_CURRENT && flags != VIR_DOMAIN_AFFECT_LIVE) {
virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -2615,7 +2615,8 @@ esxDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
esxVI_ObjectContent *hostSystem = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
- if (flags != (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
+ if (flags != (VIR_DOMAIN_AFFECT_CURRENT | VIR_DOMAIN_VCPU_MAXIMUM) &&
+ flags != (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return -1;
}
@@ -5222,7 +5223,7 @@ esxDomainGetMetadata(virDomainPtr domain, int type,
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
- if (flags != VIR_DOMAIN_AFFECT_LIVE) {
+ if (flags != VIR_DOMAIN_AFFECT_CURRENT && flags != VIR_DOMAIN_AFFECT_LIVE) {
virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
return NULL;
}
--
1.7.9.5
11 years, 6 months
[libvirt] [PATCH] esx: Implement esxDomainGetMetadata for VIR_DOMAIN_METADATA_DESCRIPTION
by Matthias Bolte
---
src/esx/esx_driver.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index b23e7f6..f53b9c4 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -5211,6 +5211,52 @@ no_memory:
#undef MATCH
+
+static char *
+esxDomainGetMetadata(virDomainPtr domain, int type,
+ const char *uri ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ char *result = NULL;
+ esxPrivate *priv = domain->conn->privateData;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *virtualMachine = NULL;
+
+ if (flags != VIR_DOMAIN_AFFECT_LIVE) {
+ virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
+ return NULL;
+ }
+
+ if (type != VIR_DOMAIN_METADATA_DESCRIPTION) {
+ virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s",
+ _("Requested metadata element is not supported"));
+ return NULL;
+ }
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "summary.config.annotation") < 0 ||
+ esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
+ propertyNameList, &virtualMachine,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_GetStringValue(virtualMachine, "summary.config.annotation",
+ &result, esxVI_Occurrence_RequiredItem) < 0 ||
+ VIR_STRDUP(result, result) < 0) {
+ goto cleanup;
+ }
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&virtualMachine);
+
+ return result;
+}
+
+
+
static virDriver esxDriver = {
.no = VIR_DRV_ESX,
.name = "ESX",
@@ -5288,6 +5334,7 @@ static virDriver esxDriver = {
.domainSnapshotHasMetadata = esxDomainSnapshotHasMetadata, /* 0.9.13 */
.domainSnapshotDelete = esxDomainSnapshotDelete, /* 0.8.0 */
.connectIsAlive = esxConnectIsAlive, /* 0.9.8 */
+ .domainGetMetadata = esxDomainGetMetadata, /* 1.0.6 */
};
--
1.7.9.5
11 years, 6 months
[libvirt] [PATCH] openvzDomainSetNetwork: use virCommand
by Michal Privoznik
Currently, the openvzDomainSetNetwork function constructs an
array of strings representing a command line for VZCTL binary.
This is a overkill since our virCommand APIs can cover all the
functionality.
---
src/openvz/openvz_driver.c | 56 ++++++++++------------------------------------
1 file changed, 12 insertions(+), 44 deletions(-)
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 129e328..db41d72 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -88,15 +88,6 @@ static void openvzDriverUnlock(struct openvz_driver *driver)
struct openvz_driver ovz_driver;
-static void cmdExecFree(const char *cmdExec[])
-{
- int i=-1;
- while (cmdExec[++i]) {
- VIR_FREE(cmdExec[i]);
- }
-}
-
-
static int
openvzDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
@@ -827,22 +818,13 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
virDomainNetDefPtr net,
virBufferPtr configBuf)
{
- int rc = 0, narg;
- const char *prog[OPENVZ_MAX_ARG];
+ int rc = 0;
char macaddr[VIR_MAC_STRING_BUFLEN];
virMacAddr host_mac;
char host_macaddr[VIR_MAC_STRING_BUFLEN];
struct openvz_driver *driver = conn->privateData;
char *opt = NULL;
-
-#define ADD_ARG_LIT(thisarg) \
- do { \
- if (narg >= OPENVZ_MAX_ARG) \
- goto no_memory; \
- if ((prog[narg++] = strdup(thisarg)) == NULL) \
- goto no_memory; \
- } while (0)
-
+ virCommandPtr cmd = NULL;
if (net == NULL)
return 0;
@@ -852,18 +834,9 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
return -1;
}
- for (narg = 0; narg < OPENVZ_MAX_ARG; narg++)
- prog[narg] = NULL;
-
- narg = 0;
-
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
- net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
- ADD_ARG_LIT(VZCTL);
- ADD_ARG_LIT("--quiet");
- ADD_ARG_LIT("set");
- ADD_ARG_LIT(vpsid);
- }
+ net->type == VIR_DOMAIN_NET_TYPE_ETHERNET)
+ cmd = virCommandNewArgList(VZCTL, "--quiet", "set", vpsid, NULL);
virMacAddrFormat(&net->mac, macaddr);
virDomainNetGenerateMAC(driver->xmlopt, &host_mac);
@@ -875,9 +848,6 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
virBuffer buf = VIR_BUFFER_INITIALIZER;
int veid = openvzGetVEID(vpsid);
- /* --netif_add ifname[,mac,host_ifname,host_mac] */
- ADD_ARG_LIT("--netif_add") ;
-
/* if user doesn't specify guest interface name,
* then we need to generate it */
if (net->data.ethernet.dev == NULL) {
@@ -922,37 +892,35 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
if (!(opt = virBufferContentAndReset(&buf)))
goto no_memory;
- ADD_ARG_LIT(opt) ;
+ /* --netif_add ifname[,mac,host_ifname,host_mac] */
+ virCommandAddArgList(cmd, "--netif_add", opt, NULL);
VIR_FREE(opt);
} else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
net->data.ethernet.ipaddr != NULL) {
/* --ipadd ip */
- ADD_ARG_LIT("--ipadd") ;
- ADD_ARG_LIT(net->data.ethernet.ipaddr) ;
+ virCommandAddArgList(cmd, "--ipadd", net->data.ethernet.ipaddr, NULL);
}
/* TODO: processing NAT and physical device */
- if (prog[0] != NULL) {
- ADD_ARG_LIT("--save");
- if (virRun(prog, NULL) < 0) {
+ if (cmd) {
+ virCommandAddArg(cmd, "--save");
+ if (virCommandRun(cmd, NULL) < 0) {
rc = -1;
goto exit;
}
}
exit:
- cmdExecFree(prog);
+ virCommandFree(cmd);
return rc;
no_memory:
VIR_FREE(opt);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Could not put argument to %s"), VZCTL);
- cmdExecFree(prog);
+ virCommandFree(cmd);
return -1;
-
-#undef ADD_ARG_LIT
}
--
1.8.2.1
11 years, 6 months
[libvirt] [libvirt-perl PATCH] interface: list active and inactive interface by default
by Guannan Ren
flags with 0 can not list interfaces, use flags in libvirt.h
by default to list all of active and inactive interfaces
VIR_CONNECT_LIST_INTERFACES_INACTIVE = 1 << 0
VIR_CONNECT_LIST_INTERFACES_ACTIVE = 1 << 1
---
Virt.xs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Virt.xs b/Virt.xs
index a22cd2f..ea45e34 100644
--- a/Virt.xs
+++ b/Virt.xs
@@ -1980,7 +1980,8 @@ list_all_domains(con, flags=0)
void
-list_all_interfaces(con, flags=0)
+list_all_interfaces(con, flags=VIR_CONNECT_LIST_INTERFACES_ACTIVE|
+ VIR_CONNECT_LIST_INTERFACES_INACTIVE)
virConnectPtr con;
unsigned int flags;
PREINIT:
--
1.8.1.4
11 years, 6 months