[libvirt] [PATCHv4] python: Expose virDomain{G, S}etInterfaceParameters APIs in python binding
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
The v4 patch corrects indentation issues.
The v3 patch follows latest python binding codes and change 'size'
type from int to Py_ssize_t.
An simple example to show how to use it:
#!/usr/bin/env python
import libvirt
conn = libvirt.open(None)
dom = conn.lookupByName('foo')
print dom.interfaceParameters('vnet0', 0)
params = {'outbound.peak': 10,
'inbound.peak': 10,
'inbound.burst': 20,
'inbound.average': 20,
'outbound.average': 30,
'outbound.burst': 30}
print dom.setInterfaceParameters('vnet0', params, 0)
print dom.interfaceParameters('vnet0', 0)
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
python/libvirt-override-api.xml | 16 +++++
python/libvirt-override.c | 126 +++++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 563dd46..ab8f33a 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -261,6 +261,22 @@
<arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
<arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
</function>
+ <function name='virDomainSetInterfaceParameters' file='python'>
+ <info>Change the bandwidth tunables for a interface device</info>
+ <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='device' type='const char *' info='interface name'/>
+ <arg name='params' type='virTypedParameterPtr' info='Pointer to bandwidth tuning params object'/>
+ <arg name='flags' type='unsigned int' info='an OR'ed set of virDomainModificationImpact'/>
+ <return type='int' info='0 in case of success, -1 in case of failure'/>
+ </function>
+ <function name='virDomainGetInterfaceParameters' file='python'>
+ <info>Get the bandwidth tunables for a interface device</info>
+ <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='device' type='const char *' info='interface name'/>
+ <arg name='flags' type='unsigned int' info='an OR'ed set of virDomainModificationImpact'/>
+ <return type='str *' info='the bandwidth tunables value or None in case of error'/>
+ </function>
+
<function name='virConnectListStoragePools' file='python'>
<info>list the storage pools, stores the pointers to the names in @names</info>
<arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 4e8a97e..078324e 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -1109,6 +1109,130 @@ cleanup:
}
static PyObject *
+libvirt_virDomainSetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ PyObject *ret = NULL;
+ int i_retval;
+ int nparams = 0;
+ Py_ssize_t size = 0;
+ unsigned int flags;
+ const char *device = NULL;
+ virTypedParameterPtr params, new_params;
+
+ if (!PyArg_ParseTuple(args,
+ (char *)"OzOi:virDomainSetInterfaceParameters",
+ &pyobj_domain, &device, &info, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if ((size = PyDict_Size(info)) < 0)
+ return NULL;
+
+ if (size == 0) {
+ PyErr_Format(PyExc_LookupError,
+ "Need non-empty dictionary to set attributes");
+ return NULL;
+ }
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, NULL, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ return VIR_PY_INT_FAIL;
+
+ if (nparams == 0) {
+ PyErr_Format(PyExc_LookupError,
+ "Domain has no settable attributes");
+ return NULL;
+ }
+
+ if (VIR_ALLOC_N(params, nparams) < 0)
+ return PyErr_NoMemory();
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, params, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ ret = VIR_PY_INT_FAIL;
+ goto cleanup;
+ }
+
+ new_params = setPyVirTypedParameter(info, params, nparams);
+ if (!new_params)
+ goto cleanup;
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainSetInterfaceParameters(domain, device, new_params, size, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ ret = VIR_PY_INT_FAIL;
+ goto cleanup;
+ }
+
+ ret = VIR_PY_INT_SUCCESS;
+
+cleanup:
+ virTypedParameterArrayClear(params, nparams);
+ VIR_FREE(params);
+ VIR_FREE(new_params);
+ return ret;
+}
+
+static PyObject *
+libvirt_virDomainGetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain;
+ PyObject *ret = NULL;
+ int i_retval;
+ int nparams = 0;
+ unsigned int flags;
+ const char *device = NULL;
+ virTypedParameterPtr params;
+
+ if (!PyArg_ParseTuple(args, (char *)"Ozi:virDomainGetInterfaceParameters",
+ &pyobj_domain, &device, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, NULL, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ return VIR_PY_NONE;
+
+ if (!nparams)
+ return PyDict_New();
+
+ if (VIR_ALLOC_N(params, nparams) < 0)
+ return PyErr_NoMemory();
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, params, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ ret = VIR_PY_NONE;
+ goto cleanup;
+ }
+
+ ret = getPyVirTypedParameter(params, nparams);
+
+cleanup:
+ virTypedParameterArrayClear(params, nparams);
+ VIR_FREE(params);
+ return ret;
+}
+
+static PyObject *
libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) {
virDomainPtr domain;
@@ -5256,6 +5380,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virDomainGetMemoryParameters", libvirt_virDomainGetMemoryParameters, METH_VARARGS, NULL},
{(char *) "virDomainSetNumaParameters", libvirt_virDomainSetNumaParameters, METH_VARARGS, NULL},
{(char *) "virDomainGetNumaParameters", libvirt_virDomainGetNumaParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainSetInterfaceParameters", libvirt_virDomainSetInterfaceParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainGetInterfaceParameters", libvirt_virDomainGetInterfaceParameters, METH_VARARGS, NULL},
{(char *) "virDomainGetVcpus", libvirt_virDomainGetVcpus, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpuFlags", libvirt_virDomainPinVcpuFlags, METH_VARARGS, NULL},
--
1.7.1
12 years, 8 months
[libvirt] [PATCH] snapshot: fix snapshot deletion
by Eric Blake
Bug introduced in commit 35abced. On an inactive domain,
$ virsh snapshot-create-as dom snap
$ virsh snapshot-create dom
$ virsh snapshot-create dom
$ virsh snapshot-delete --children dom snap
could crash libvirtd, due to a use-after-free that results
when the callback freed the current element in the iteration.
* src/conf/domain_conf.c (virDomainSnapshotForEachChild)
(virDomainSnapshotActOnDescendant): Allow iteration to delete
current child.
---
src/conf/domain_conf.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f8d0a4c..da00830 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13325,8 +13325,9 @@ virDomainSnapshotForEachChild(virDomainSnapshotObjPtr snapshot,
virDomainSnapshotObjPtr child = snapshot->first_child;
while (child) {
+ virDomainSnapshotObjPtr next = child->sibling;
(iter)(child, child->def->name, data);
- child = child->sibling;
+ child = next;
}
return snapshot->nchildren;
@@ -13346,10 +13347,10 @@ virDomainSnapshotActOnDescendant(void *payload,
virDomainSnapshotObjPtr obj = payload;
struct snapshot_act_on_descendant *curr = data;
- (curr->iter)(payload, name, curr->data);
curr->number += 1 + virDomainSnapshotForEachDescendant(obj,
curr->iter,
curr->data);
+ (curr->iter)(payload, name, curr->data);
}
/* Run iter(data) on all descendants of snapshot, while ignoring all
--
1.7.7.6
12 years, 8 months
[libvirt] [PATCH] daemon: plug memory leak
by Eric Blake
Leak introduced in commit bb2eddc6.
* daemon/remote.c (remoteDispatchAuthPolkit): Also free pkout on
success.
---
daemon/remote.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 1cea942..9c61306 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -2536,6 +2536,7 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED,
virNetServerClientSetIdentity(client, ident);
virMutexUnlock(&priv->lock);
virCommandFree(cmd);
+ VIR_FREE(pkout);
VIR_FREE(ident);
return 0;
--
1.7.7.6
12 years, 8 months
[libvirt] libvirtError: internal error cannot create rule since ebtables tool is missing.
by Phantomcircuit
# libvirtd --version
libvirtd (libvirt) 0.9.8
# which ebtables
/sbin/ebtables
2012-02-15 09:40:59.083+0000: 17675: error :
ebtablesCreateRuleInstance:1943 : internal error cannot create rule
since ebtables tool is missing.
2012-02-15 09:40:59.107+0000: 17675: error : virNetDevGetIndex:656 :
Unable to get index for interface vnet0: No such device
ebtables_cmd_path = virFindFileInPath("ebtables");
I can't figure out why ebtables_cmd_path is NULL when the call to
ebtablesCreateRuleInstance is made.
12 years, 8 months
[libvirt] [PATCH] qemu: Prevent crash of libvirtd without guest agent
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
* src/qemu/qemu_process.c (qemuFindAgentConfig): avoid crash libvirtd due to
deref a NULL pointer.
* How to reproduce?
1. virsh edit the following xml into guest configuration:
<channel type='pty'>
<target type='virtio'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
2. virsh start <domain>
or
% virt-install -n foo -r 1024 --disk path=/var/lib/libvirt/images/foo.img,size=1 \
--channel pty,target_type=virtio -l <installation tree>
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
src/qemu/qemu_process.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 2d92d66..6dc1732 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -189,11 +189,14 @@ qemuFindAgentConfig(virDomainDefPtr def)
for (i = 0 ; i < def->nchannels ; i++) {
virDomainChrDefPtr channel = def->channels[i];
+ if(!channel)
+ break;
if (channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
continue;
- if (STREQ(channel->target.name, "org.qemu.guest_agent.0")) {
+ if (channel->target.name &&
+ STREQ(channel->target.name, "org.qemu.guest_agent.0")) {
config = &channel->source;
break;
}
--
1.7.1
12 years, 8 months
[libvirt] [PATCH v2] RFC Libvirt + Openvswitch
by Ansis Atteka
This patch allows libvirt to add interfaces to already
existing Open vSwitch bridges. The following syntax in
domain XML file can be used:
<interface type='bridge'>
<mac address='52:54:00:d0:3f:f2'/>
<source bridge='ovsbr'/>
<virtualport type='openvswitch'>
<parameters interfaceid='921a80cd-e6de-5a2e-db9c-ab27f15a6e1d'/>
</virtualport>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
or if libvirt should auto-generate the interfaceid use
following syntax:
<interface type='bridge'>
<mac address='52:54:00:d0:3f:f2'/>
<source bridge='ovsbr'/>
<virtualport type='openvswitch'>
</virtualport>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
It is also possible to pass an optional profileid. To do that
use following syntax:
<interface type='bridge'>
<source bridge='ovsbr'/>
<mac address='00:55:1a:65:a2:8d'/>
<virtualport type='openvswitch'>
<parameters interfaceid='921a80cd-e6de-5a2e-db9c-ab27f15a6e1d' profileid='test-profile'/>
</virtualport>
</interface>
To create Open vSwitch bridge install Open vSwitch and
run the following command:
ovs-vsctl add-br ovsbr
---
configure.ac | 5 +
src/Makefile.am | 1 +
src/conf/domain_conf.c | 51 +++++++++++--
src/conf/domain_conf.h | 5 +-
src/conf/netdev_vport_profile_conf.c | 47 +++++++++++-
src/libvirt_private.syms | 7 ++-
src/lxc/lxc_driver.c | 37 +++++++--
src/network/bridge_driver.c | 3 +-
src/qemu/qemu_command.c | 5 +-
src/qemu/qemu_hotplug.c | 17 ++++-
src/qemu/qemu_migration.c | 4 +-
src/qemu/qemu_process.c | 10 ++-
src/uml/uml_conf.c | 3 +-
src/util/virnetdevopenvswitch.c | 135 ++++++++++++++++++++++++++++++++++
src/util/virnetdevopenvswitch.h | 42 +++++++++++
src/util/virnetdevtap.c | 14 +++-
src/util/virnetdevtap.h | 5 +-
src/util/virnetdevvportprofile.c | 2 +
src/util/virnetdevvportprofile.h | 7 ++-
19 files changed, 365 insertions(+), 35 deletions(-)
create mode 100644 src/util/virnetdevopenvswitch.c
create mode 100644 src/util/virnetdevopenvswitch.h
diff --git a/configure.ac b/configure.ac
index 9fb7bfc..dca178f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -213,6 +213,8 @@ AC_PATH_PROG([UDEVSETTLE], [udevsettle], [],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_PATH_PROG([MODPROBE], [modprobe], [],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
+AC_PATH_PROG([OVSVSCTL], [ovs-vsctl], [ovs-vsctl],
+ [/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_DEFINE_UNQUOTED([DNSMASQ],["$DNSMASQ"],
[Location or name of the dnsmasq program])
@@ -220,6 +222,9 @@ AC_DEFINE_UNQUOTED([RADVD],["$RADVD"],
[Location or name of the radvd program])
AC_DEFINE_UNQUOTED([TC],["$TC"],
[Location or name of the tc profram (see iproute2)])
+AC_DEFINE_UNQUOTED([OVSVSCTL],["$OVSVSCTL"],
+ [Location or name of the ovs-vsctl program])
+
if test -n "$UDEVADM"; then
AC_DEFINE_UNQUOTED([UDEVADM],["$UDEVADM"],
[Location or name of the udevadm program])
diff --git a/src/Makefile.am b/src/Makefile.am
index a3dd847..d5f52a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -97,6 +97,7 @@ UTIL_SOURCES = \
util/virnetdevbandwidth.h util/virnetdevbandwidth.c \
util/virnetdevbridge.h util/virnetdevbridge.c \
util/virnetdevmacvlan.c util/virnetdevmacvlan.h \
+ util/virnetdevopenvswitch.h util/virnetdevopenvswitch.c \
util/virnetdevtap.h util/virnetdevtap.c \
util/virnetdevveth.h util/virnetdevveth.c \
util/virnetdevvportprofile.h util/virnetdevvportprofile.c \
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a09a506..5b5db43 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31,6 +31,7 @@
#include <sys/time.h>
#include <strings.h>
+#include "internal.h"
#include "virterror_internal.h"
#include "datatypes.h"
#include "domain_conf.h"
@@ -951,6 +952,7 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
+ VIR_FREE(def->data.bridge.ovsPort);
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
VIR_FREE(def->data.direct.linkdev);
@@ -994,6 +996,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
VIR_FREE(def->data.bridge.ipaddr);
+ VIR_FREE(def->data.bridge.ovsPort);
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
@@ -3732,7 +3735,11 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
}
if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
- actual->data.bridge.brname = virXPathString("string(./source[1]/@bridge)", ctxt);
+ xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
+ if (virtPortNode &&
+ (!(actual->data.bridge.ovsPort =
+ virNetDevVPortProfileParse(virtPortNode))))
+ goto error;
} else if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
xmlNodePtr virtPortNode;
@@ -3861,7 +3868,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
mode = virXMLPropString(cur, "mode");
} else if ((virtPort == NULL) &&
((def->type == VIR_DOMAIN_NET_TYPE_DIRECT) ||
- (def->type == VIR_DOMAIN_NET_TYPE_NETWORK)) &&
+ (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) ||
+ (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE)) &&
xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
if (!(virtPort = virNetDevVPortProfileParse(cur)))
goto error;
@@ -4000,6 +4008,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
def->data.bridge.ipaddr = address;
address = NULL;
}
+ def->data.bridge.ovsPort = virtPort;
+ virtPort = NULL;
break;
case VIR_DOMAIN_NET_TYPE_CLIENT:
@@ -10429,6 +10439,12 @@ virDomainActualNetDefFormat(virBufferPtr buf,
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferEscapeString(buf, " <source bridge='%s'/>\n",
def->data.bridge.brname);
+ if (def->data.bridge.ovsPort) {
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevVPortProfileFormat(def->data.bridge.ovsPort, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+ }
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
@@ -10516,6 +10532,12 @@ virDomainNetDefFormat(virBufferPtr buf,
if (def->data.bridge.ipaddr)
virBufferAsprintf(buf, " <ip address='%s'/>\n",
def->data.bridge.ipaddr);
+ if (def->data.bridge.ovsPort) {
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevVPortProfileFormat(def->data.bridge.ovsPort, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+ }
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
@@ -13832,15 +13854,27 @@ virDomainNetGetActualDirectMode(virDomainNetDefPtr iface)
}
virNetDevVPortProfilePtr
-virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface)
+virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
{
- if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ switch (iface->type) {
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
return iface->data.direct.virtPortProfile;
- if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
- return NULL;
- if (!iface->data.network.actual)
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ return iface->data.bridge.ovsPort;
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ if (!iface->data.network.actual)
+ return NULL;
+ switch (iface->data.network.actual->type) {
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ return iface->data.network.actual->data.direct.virtPortProfile;
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ return iface->data.network.actual->data.bridge.ovsPort;
+ default:
+ return NULL;
+ }
+ default:
return NULL;
- return iface->data.network.actual->data.direct.virtPortProfile;
+ }
}
virNetDevBandwidthPtr
@@ -13853,7 +13887,6 @@ virDomainNetGetActualBandwidth(virDomainNetDefPtr iface)
return iface->bandwidth;
}
-
/* Return listens[ii] from the appropriate union for the graphics
* type, or NULL if this is an unsuitable type, or the index is out of
* bounds. If force0 is TRUE, ii == 0, and there is no listen array,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8bb21cf..c4c3551 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -41,6 +41,7 @@
# include "virnetdevmacvlan.h"
# include "sysinfo.h"
# include "virnetdevvportprofile.h"
+# include "virnetdevopenvswitch.h"
# include "virnetdevbandwidth.h"
/* Different types of hypervisor */
@@ -596,6 +597,7 @@ struct _virDomainActualNetDef {
union {
struct {
char *brname;
+ virNetDevVPortProfilePtr ovsPort;
} bridge;
struct {
char *linkdev;
@@ -647,6 +649,7 @@ struct _virDomainNetDef {
struct {
char *brname;
char *ipaddr;
+ virNetDevVPortProfilePtr ovsPort;
} bridge;
struct {
char *name;
@@ -1875,7 +1878,7 @@ const char *virDomainNetGetActualBridgeName(virDomainNetDefPtr iface);
const char *virDomainNetGetActualDirectDev(virDomainNetDefPtr iface);
int virDomainNetGetActualDirectMode(virDomainNetDefPtr iface);
virNetDevVPortProfilePtr
-virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface);
+virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface);
virNetDevBandwidthPtr
virDomainNetGetActualBandwidth(virDomainNetDefPtr iface);
diff --git a/src/conf/netdev_vport_profile_conf.c b/src/conf/netdev_vport_profile_conf.c
index b48b2cb..205d674 100644
--- a/src/conf/netdev_vport_profile_conf.c
+++ b/src/conf/netdev_vport_profile_conf.c
@@ -35,7 +35,8 @@
VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST,
"none",
"802.1Qbg",
- "802.1Qbh")
+ "802.1Qbh",
+ "openvswitch")
virNetDevVPortProfilePtr
@@ -47,6 +48,7 @@ virNetDevVPortProfileParse(xmlNodePtr node)
char *virtPortTypeIDVersion = NULL;
char *virtPortInstanceID = NULL;
char *virtPortProfileID = NULL;
+ char *virtPortInterfaceID = NULL;
virNetDevVPortProfilePtr virtPort = NULL;
xmlNodePtr cur = node->children;
@@ -76,7 +78,7 @@ virNetDevVPortProfileParse(xmlNodePtr node)
virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
virtPortInstanceID = virXMLPropString(cur, "instanceid");
virtPortProfileID = virXMLPropString(cur, "profileid");
-
+ virtPortInterfaceID = virXMLPropString(cur, "interfaceid");
break;
}
@@ -171,6 +173,33 @@ virNetDevVPortProfileParse(xmlNodePtr node)
goto error;
}
break;
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
+ if (virtPortInterfaceID != NULL) {
+ if (virUUIDParse(virtPortInterfaceID,
+ virtPort->u.openvswitch.interfaceID)) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse interfaceid parameter as a uuid"));
+ goto error;
+ }
+ } else {
+ if (virUUIDGenerate(virtPort->u.openvswitch.interfaceID)) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot generate a random uuid for interfaceid"));
+ goto error;
+ }
+ }
+ /* profileid is not mandatory for Open vSwitch */
+ if (virtPortProfileID != NULL) {
+ if (virStrcpyStatic(virtPort->u.openvswitch.profileID,
+ virtPortProfileID) == NULL) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("profileid parameter too long"));
+ goto error;
+ }
+ } else {
+ virtPort->u.openvswitch.profileID[0] = '\0';
+ }
+ break;
default:
virNetDevError(VIR_ERR_XML_ERROR,
@@ -225,6 +254,20 @@ virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort,
virtPort->u.virtPort8021Qbh.profileID);
break;
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
+ virUUIDFormat(virtPort->u.openvswitch.interfaceID,
+ uuidstr);
+ if (virtPort->u.openvswitch.profileID[0] == '\0') {
+ virBufferAsprintf(buf, " <parameters interfaceid='%s'/>\n",
+ uuidstr);
+ } else {
+ virBufferAsprintf(buf, " <parameters interfaceid='%s' "
+ "profileid='%s'/>\n", uuidstr,
+ virtPort->u.openvswitch.profileID);
+ }
+
+ break;
+
default:
virNetDevError(VIR_ERR_XML_ERROR,
_("unexpected virtualport type %d"), virtPort->virtPortType);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0c22dec..ad5c7d3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -378,7 +378,7 @@ virDomainNetGetActualBandwidth;
virDomainNetGetActualBridgeName;
virDomainNetGetActualDirectDev;
virDomainNetGetActualDirectMode;
-virDomainNetGetActualDirectVirtPortProfile;
+virDomainNetGetActualVirtPortProfile;
virDomainNetGetActualType;
virDomainNetIndexByMac;
virDomainNetInsert;
@@ -1237,6 +1237,11 @@ virNetDevMacVLanCreateWithVPortProfile;
virNetDevMacVLanDeleteWithVPortProfile;
+# virnetdevopenvswitch.h
+virNetDevOpenvswitchAddPort;
+virNetDevOpenvswitchRemovePort;
+
+
# virnetdevtap.h
virNetDevTapCreate;
virNetDevTapCreateInBridgePort;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index b712da4..17e8312 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -56,6 +56,7 @@
#include "domain_nwfilter.h"
#include "network/bridge_driver.h"
#include "virnetdev.h"
+#include "virnetdevtap.h"
#include "virnodesuspend.h"
#include "virtime.h"
#include "virtypedparam.h"
@@ -1105,6 +1106,7 @@ static void lxcVmCleanup(lxc_driver_t *driver,
virCgroupPtr cgroup;
int i;
lxcDomainObjPrivatePtr priv = vm->privateData;
+ virNetDevVPortProfilePtr vport = NULL;
/* now that we know it's stopped call the hook if present */
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
@@ -1132,10 +1134,15 @@ static void lxcVmCleanup(lxc_driver_t *driver,
priv->monitorWatch = -1;
for (i = 0 ; i < vm->def->nnets ; i++) {
- ignore_value(virNetDevSetOnline(vm->def->nets[i]->ifname, false));
- ignore_value(virNetDevVethDelete(vm->def->nets[i]->ifname));
-
- networkReleaseActualDevice(vm->def->nets[i]);
+ virDomainNetDefPtr iface = vm->def->nets[i];
+ vport = virDomainNetGetActualVirtPortProfile(iface);
+ ignore_value(virNetDevSetOnline(iface->ifname, false));
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(iface),
+ iface->ifname));
+ ignore_value(virNetDevVethDelete(iface->ifname));
+ networkReleaseActualDevice(iface);
}
virDomainConfVMNWFilterTeardown(vm);
@@ -1165,6 +1172,7 @@ static int lxcSetupInterfaceBridged(virConnectPtr conn,
int ret = -1;
char *parentVeth;
char *containerVeth = NULL;
+ const virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net);
VIR_DEBUG("calling vethCreate()");
parentVeth = net->ifname;
@@ -1186,7 +1194,11 @@ static int lxcSetupInterfaceBridged(virConnectPtr conn,
if (virNetDevSetMAC(containerVeth, net->mac) < 0)
goto cleanup;
- if (virNetDevBridgeAddPort(brname, parentVeth) < 0)
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ret = virNetDevOpenvswitchAddPort(brname, parentVeth, net->mac, vport);
+ else
+ ret = virNetDevBridgeAddPort(brname, parentVeth);
+ if (ret < 0)
goto cleanup;
if (virNetDevSetOnline(parentVeth, true) < 0)
@@ -1242,7 +1254,7 @@ static int lxcSetupInterfaceDirect(virConnectPtr conn,
* and automagically dies when the container dies. So
* we have no dev to perform disassociation with.
*/
- prof = virDomainNetGetActualDirectVirtPortProfile(net);
+ prof = virDomainNetGetActualVirtPortProfile(net);
if (prof) {
lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Unable to set port profile on direct interfaces"));
@@ -1260,7 +1272,7 @@ static int lxcSetupInterfaceDirect(virConnectPtr conn,
virDomainNetGetActualDirectDev(net),
virDomainNetGetActualDirectMode(net),
false, false, def->uuid,
- virDomainNetGetActualDirectVirtPortProfile(net),
+ virDomainNetGetActualVirtPortProfile(net),
&res_ifname,
VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
driver->stateDir,
@@ -1377,8 +1389,15 @@ static int lxcSetupInterfaces(virConnectPtr conn,
cleanup:
if (ret != 0) {
- for (i = 0 ; i < def->nnets ; i++)
- networkReleaseActualDevice(def->nets[i]);
+ for (i = 0 ; i < def->nnets ; i++) {
+ virDomainNetDefPtr iface = def->nets[i];
+ virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(iface);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(iface),
+ iface->ifname));
+ networkReleaseActualDevice(iface);
+ }
}
return ret;
}
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 57ebb9f..1423d3f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1765,7 +1765,8 @@ networkStartNetworkVirtual(struct network_driver *driver,
goto err0;
}
if (virNetDevTapCreateInBridgePort(network->def->bridge,
- &macTapIfName, network->def->mac, 0, false, NULL) < 0) {
+ &macTapIfName, network->def->mac, 0,
+ false, NULL, NULL) < 0) {
VIR_FREE(macTapIfName);
goto err0;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1b92aa4..591e371 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -154,7 +154,7 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
virDomainNetGetActualDirectDev(net),
virDomainNetGetActualDirectMode(net),
true, vnet_hdr, def->uuid,
- virDomainNetGetActualDirectVirtPortProfile(net),
+ virDomainNetGetActualVirtPortProfile(net),
&res_ifname,
vmop, driver->stateDir,
virDomainNetGetActualBandwidth(net));
@@ -247,7 +247,8 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
err = virNetDevTapCreateInBridgePort(brname, &net->ifname, tapmac,
- vnet_hdr, true, &tapfd);
+ vnet_hdr, true, &tapfd,
+ virDomainNetGetActualVirtPortProfile(net));
virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0);
if (err < 0) {
if (template_ifname)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b4870be..3b1dbbf 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -40,6 +40,7 @@
#include "qemu_cgroup.h"
#include "locking/domain_lock.h"
#include "network/bridge_driver.h"
+#include "virnetdevtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -652,6 +653,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
int vhostfd = -1;
char *nicstr = NULL;
char *netstr = NULL;
+ virNetDevVPortProfilePtr vport = NULL;
int ret = -1;
virDomainDevicePCIAddress guestAddr;
int vlan;
@@ -838,6 +840,12 @@ cleanup:
if (iface_connected)
virDomainConfNWFilterTeardown(net);
+ vport = virDomainNetGetActualVirtPortProfile(net);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(net),
+ net->ifname));
+
networkReleaseActualDevice(net);
}
@@ -1833,6 +1841,7 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
int vlan;
char *hostnet_name = NULL;
+ virNetDevVPortProfilePtr vport = NULL;
for (i = 0 ; i < vm->def->nnets ; i++) {
virDomainNetDefPtr net = vm->def->nets[i];
@@ -1923,7 +1932,7 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
detach->ifname, detach->mac,
virDomainNetGetActualDirectDev(detach),
virDomainNetGetActualDirectMode(detach),
- virDomainNetGetActualDirectVirtPortProfile(detach),
+ virDomainNetGetActualVirtPortProfile(detach),
driver->stateDir));
VIR_FREE(detach->ifname);
}
@@ -1938,6 +1947,12 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
}
}
+ vport = virDomainNetGetActualVirtPortProfile(detach);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(detach),
+ detach->ifname));
+
networkReleaseActualDevice(detach);
if (vm->def->nnets > 1) {
memmove(vm->def->nets + i,
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 12cfbde..a513b3c 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2563,7 +2563,7 @@ qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def) {
net = def->nets[i];
if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
if (virNetDevVPortProfileAssociate(net->ifname,
- virDomainNetGetActualDirectVirtPortProfile(net),
+ virDomainNetGetActualVirtPortProfile(net),
net->mac,
virDomainNetGetActualDirectDev(net),
def->uuid,
@@ -2580,7 +2580,7 @@ err_exit:
net = def->nets[i];
if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
ignore_value(virNetDevVPortProfileDisassociate(net->ifname,
- virDomainNetGetActualDirectVirtPortProfile(net),
+ virDomainNetGetActualVirtPortProfile(net),
net->mac,
virDomainNetGetActualDirectDev(net),
VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH));
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 2d92d66..9bc5436 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -62,6 +62,7 @@
#include "network/bridge_driver.h"
#include "uuid.h"
#include "virtime.h"
+#include "virnetdevtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -3604,6 +3605,7 @@ void qemuProcessStop(struct qemud_driver *driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
virErrorPtr orig_err;
virDomainDefPtr def;
+ virNetDevVPortProfilePtr vport = NULL;
int i;
int logfile = -1;
char *timestamp;
@@ -3724,13 +3726,19 @@ void qemuProcessStop(struct qemud_driver *driver,
net->ifname, net->mac,
virDomainNetGetActualDirectDev(net),
virDomainNetGetActualDirectMode(net),
- virDomainNetGetActualDirectVirtPortProfile(net),
+ virDomainNetGetActualVirtPortProfile(net),
driver->stateDir));
VIR_FREE(net->ifname);
}
/* release the physical device (or any other resources used by
* this interface in the network driver
*/
+ vport = virDomainNetGetActualVirtPortProfile(net);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(net),
+ net->ifname));
+
networkReleaseActualDevice(net);
}
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 316d558..8c17578 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -142,7 +142,8 @@ umlConnectTapDevice(virConnectPtr conn,
memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, tapmac,
- 0, true, NULL) < 0) {
+ 0, true, NULL,
+ virDomainNetGetActualVirtPortProfile(net)) < 0) {
if (template_ifname)
VIR_FREE(net->ifname);
goto error;
diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
new file mode 100644
index 0000000..24a335a
--- /dev/null
+++ b/src/util/virnetdevopenvswitch.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 Nicira, 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
+ *
+ * Authors:
+ * Dan Wendlandt <dan(a)nicira.com>
+ * Kyle Mestery <kmestery(a)cisco.com>
+ * Ansis Atteka <aatteka(a)nicira.com>
+ */
+
+#include <config.h>
+
+#include "virnetdevopenvswitch.h"
+#include "command.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "ignore-value.h"
+#include "virmacaddr.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+/**
+ * virNetDevOpenvswitchAddPort:
+ * @brname: the bridge name
+ * @ifname: the network interface name
+ * @macaddr: the mac address of the virtual interface
+ * @ovsport: the ovs specific fields
+ *
+ * Add an interface to the OVS bridge
+ *
+ * Returns 0 in case of success or -1 in case of failure.
+ */
+int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+ const unsigned char *macaddr,
+ virNetDevVPortProfilePtr ovsport)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+ char macaddrstr[VIR_MAC_STRING_BUFLEN];
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *attachedmac_ex_id = NULL;
+ char *ifaceid_ex_id = NULL;
+ char *profile_ex_id = NULL;
+
+ virMacAddrFormat(macaddr, macaddrstr);
+ virUUIDFormat(ovsport->u.openvswitch.interfaceID, uuidstr);
+
+ if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
+ macaddrstr) < 0)
+ goto cleanup;
+ if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
+ uuidstr) < 0)
+ goto cleanup;
+ if (ovsport->u.openvswitch.profileID[0] != '\0') {
+ if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
+ ovsport->u.openvswitch.profileID) < 0)
+ goto cleanup;
+ }
+
+ cmd = virCommandNew(OVSVSCTL);
+ if (ovsport->u.openvswitch.profileID[0] == '\0') {
+ virCommandAddArgList(cmd, "--", "--may-exist", "add-port",
+ brname, ifname,
+ "--", "set", "Interface", ifname, attachedmac_ex_id,
+ "--", "set", "Interface", ifname, ifaceid_ex_id,
+ "--", "set", "Interface", ifname,
+ "external-ids:iface-status=active",
+ NULL);
+ } else {
+ virCommandAddArgList(cmd, "--", "--may-exist", "add-port",
+ brname, ifname,
+ "--", "set", "Interface", ifname, attachedmac_ex_id,
+ "--", "set", "Interface", ifname, ifaceid_ex_id,
+ "--", "set", "Interface", ifname, profile_ex_id,
+ "--", "set", "Interface", ifname,
+ "external-ids:iface-status=active",
+ NULL);
+ }
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to add port %s to OVS bridge %s"),
+ ifname, brname);
+ goto cleanup;
+ }
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(attachedmac_ex_id);
+ VIR_FREE(ifaceid_ex_id);
+ VIR_FREE(profile_ex_id);
+ virCommandFree(cmd);
+ return ret;
+}
+
+/**
+ * virNetDevOpenvswitchRemovePort:
+ * @ifname: the network interface name
+ *
+ * Deletes an interface from a OVS bridge
+ *
+ * Returns 0 in case of success or -1 in case of failure.
+ */
+int virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, const char *ifname)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+
+ cmd = virCommandNew(OVSVSCTL);
+ virCommandAddArgList(cmd, "--", "--if-exists", "del-port", ifname, NULL);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to delete port %s from OVS"), ifname);
+ goto cleanup;
+ }
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h
new file mode 100644
index 0000000..bca4c3e
--- /dev/null
+++ b/src/util/virnetdevopenvswitch.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Nicira, 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
+ *
+ * Authors:
+ * Dan Wendlandt <dan(a)nicira.com>
+ * Kyle Mestery <kmestery(a)cisco.com>
+ * Ansis Atteka <aatteka(a)nicira.com>
+ */
+
+#ifndef __VIR_NETDEV_OPENVSWITCH_H__
+# define __VIR_NETDEV_OPENVSWITCH_H__
+
+# include "internal.h"
+# include "util.h"
+# include "virnetdevvportprofile.h"
+
+
+int virNetDevOpenvswitchAddPort(const char *brname,
+ const char *ifname,
+ const unsigned char *macaddr,
+ virNetDevVPortProfilePtr ovsport)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevOpenvswitchRemovePort(const char *brname, const char *ifname)
+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+#endif /* __VIR_NETDEV_OPENVSWITCH_H__ */
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
index 2ed53c6..cd1d4c1 100644
--- a/src/util/virnetdevtap.c
+++ b/src/util/virnetdevtap.c
@@ -25,6 +25,7 @@
#include "virnetdevtap.h"
#include "virnetdev.h"
#include "virnetdevbridge.h"
+#include "virnetdevopenvswitch.h"
#include "virterror_internal.h"
#include "virfile.h"
#include "virterror_internal.h"
@@ -249,6 +250,7 @@ int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED)
* @macaddr: desired MAC address (VIR_MAC_BUFLEN long)
* @vnet_hdr: whether to try enabling IFF_VNET_HDR
* @tapfd: file descriptor return value for the new tap device
+ * @ovsport: Open vSwitch specific configuration
*
* This function creates a new tap device on a bridge. @ifname can be either
* a fixed name or a name template with '%d' for dynamic name allocation.
@@ -265,7 +267,8 @@ int virNetDevTapCreateInBridgePort(const char *brname,
const unsigned char *macaddr,
int vnet_hdr,
bool up,
- int *tapfd)
+ int *tapfd,
+ virNetDevVPortProfilePtr ovsport)
{
if (virNetDevTapCreate(ifname, vnet_hdr, tapfd) < 0)
return -1;
@@ -286,8 +289,13 @@ int virNetDevTapCreateInBridgePort(const char *brname,
if (virNetDevSetMTUFromDevice(*ifname, brname) < 0)
goto error;
- if (virNetDevBridgeAddPort(brname, *ifname) < 0)
- goto error;
+ if (ovsport) {
+ if (virNetDevOpenvswitchAddPort(brname, *ifname, macaddr, ovsport) < 0)
+ goto error;
+ } else {
+ if (virNetDevBridgeAddPort(brname, *ifname) < 0)
+ goto error;
+ }
if (virNetDevSetOnline(*ifname, up) < 0)
goto error;
diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h
index fb35ac5..ee159f7 100644
--- a/src/util/virnetdevtap.h
+++ b/src/util/virnetdevtap.h
@@ -24,6 +24,7 @@
# define __VIR_NETDEV_TAP_H__
# include "internal.h"
+# include "virnetdevvportprofile.h"
int virNetDevTapCreate(char **ifname,
int vnet_hdr,
@@ -38,8 +39,10 @@ int virNetDevTapCreateInBridgePort(const char *brname,
const unsigned char *macaddr,
int vnet_hdr,
bool up,
- int *tapfd)
+ int *tapfd,
+ virNetDevVPortProfilePtr ovsport)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_RETURN_CHECK;
+
#endif /* __VIR_NETDEV_TAP_H__ */
diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c
index faadc3a..67fd7bc 100644
--- a/src/util/virnetdevvportprofile.c
+++ b/src/util/virnetdevvportprofile.c
@@ -968,6 +968,7 @@ virNetDevVPortProfileAssociate(const char *macvtap_ifname,
switch (virtPort->virtPortType) {
case VIR_NETDEV_VPORT_PROFILE_NONE:
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
case VIR_NETDEV_VPORT_PROFILE_LAST:
break;
@@ -1027,6 +1028,7 @@ virNetDevVPortProfileDisassociate(const char *macvtap_ifname,
switch (virtPort->virtPortType) {
case VIR_NETDEV_VPORT_PROFILE_NONE:
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
case VIR_NETDEV_VPORT_PROFILE_LAST:
break;
diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h
index 7a8d81f..ec2d06d 100644
--- a/src/util/virnetdevvportprofile.h
+++ b/src/util/virnetdevvportprofile.h
@@ -35,6 +35,7 @@ enum virNetDevVPortProfile {
VIR_NETDEV_VPORT_PROFILE_NONE,
VIR_NETDEV_VPORT_PROFILE_8021QBG,
VIR_NETDEV_VPORT_PROFILE_8021QBH,
+ VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH,
VIR_NETDEV_VPORT_PROFILE_LAST,
};
@@ -54,7 +55,7 @@ enum virNetDevVPortProfileOp {
};
VIR_ENUM_DECL(virNetDevVPortProfileOp)
-/* profile data for macvtap (VEPA) */
+/* profile data for macvtap (VEPA) and openvswitch */
typedef struct _virNetDevVPortProfile virNetDevVPortProfile;
typedef virNetDevVPortProfile *virNetDevVPortProfilePtr;
struct _virNetDevVPortProfile {
@@ -69,6 +70,10 @@ struct _virNetDevVPortProfile {
struct {
char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
} virtPort8021Qbh;
+ struct {
+ unsigned char interfaceID[VIR_UUID_BUFLEN];
+ char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
+ } openvswitch;
} u;
};
--
1.7.5.4
12 years, 8 months
[libvirt] [PATCHv3 0/2] qemu: mitigate 'qemu disk buffers not flushed' problem
by Laine Stump
I previously pushed a patch that adds a new flag,
VIR_DOMAIN_DESTROY_GRACEFUL, to virDomainDestroyFlags, so that a
management application can destroy a domain without danger of sending
SIGKILL to the qemu process too early (which occasionally results in a
corrupted disk image due to qemu being unable to flush its disk
buffers quickly enough).
That patch will enable management applications to solve the problem by
calling virDomainDestroyFlags with the new flag, and if they receive
an error back from libvirtd, they can decide (or let the admin decide)
when/if it is appropriate to call the more heavy-handed version of
virDomainDestroy.
However, that patch does *not* help those installations that are able
to upgrade libvirt but have no available updated management
application to install. Since the root cause of this bug is in
libvirt, we need to do our best to mitigate the situation for these people.
These two patches do two things:
1) Drop the driver lock while sleeping during qemuProcessKill(), so
that it can wait for a longer period without locking up all other
libvirtd threads.
This patch is a slight re-work of a patch Eric sent to the list back
in November.
2) Wait for a considerably longer period after sending SIGTERM before
sending SIGKILL.
12 years, 8 months
[libvirt] [PATCHv3] python: Expose virDomain{G, S}etInterfaceParameters APIs in python binding
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
The v3 patch to follow latest python binding codes and change 'size'
type from int to Py_ssize_t.
An simple example to show how to use it:
#!/usr/bin/env python
import libvirt
conn = libvirt.open(None)
dom = conn.lookupByName('foo')
print dom.interfaceParameters('vnet0', 0)
params = {'outbound.peak': 10,
'inbound.peak': 10,
'inbound.burst': 20,
'inbound.average': 20,
'outbound.average': 30,
'outbound.burst': 30}
print dom.setInterfaceParameters('vnet0', params, 0)
print dom.interfaceParameters('vnet0', 0)
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
python/libvirt-override-api.xml | 16 +++++
python/libvirt-override.c | 126 +++++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 563dd46..ab8f33a 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -261,6 +261,22 @@
<arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
<arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
</function>
+ <function name='virDomainSetInterfaceParameters' file='python'>
+ <info>Change the bandwidth tunables for a interface device</info>
+ <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='device' type='const char *' info='interface name'/>
+ <arg name='params' type='virTypedParameterPtr' info='Pointer to bandwidth tuning params object'/>
+ <arg name='flags' type='unsigned int' info='an OR'ed set of virDomainModificationImpact'/>
+ <return type='int' info='0 in case of success, -1 in case of failure'/>
+ </function>
+ <function name='virDomainGetInterfaceParameters' file='python'>
+ <info>Get the bandwidth tunables for a interface device</info>
+ <arg name='dom' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='device' type='const char *' info='interface name'/>
+ <arg name='flags' type='unsigned int' info='an OR'ed set of virDomainModificationImpact'/>
+ <return type='str *' info='the bandwidth tunables value or None in case of error'/>
+ </function>
+
<function name='virConnectListStoragePools' file='python'>
<info>list the storage pools, stores the pointers to the names in @names</info>
<arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 4e8a97e..078324e 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -1109,6 +1109,130 @@ cleanup:
}
static PyObject *
+libvirt_virDomainSetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ PyObject *ret = NULL;
+ int i_retval;
+ int nparams = 0;
+ Py_ssize_t size = 0;
+ unsigned int flags;
+ const char *device = NULL;
+ virTypedParameterPtr params, new_params;
+
+ if (!PyArg_ParseTuple(args,
+ (char *)"OzOi:virDomainSetInterfaceParameters",
+ &pyobj_domain, &device, &info, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if ((size = PyDict_Size(info)) < 0)
+ return NULL;
+
+ if (size == 0) {
+ PyErr_Format(PyExc_LookupError,
+ "Need non-empty dictionary to set attributes");
+ return NULL;
+ }
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, NULL, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ return VIR_PY_INT_FAIL;
+
+ if (nparams == 0) {
+ PyErr_Format(PyExc_LookupError,
+ "Domain has no settable attributes");
+ return NULL;
+ }
+
+ if (VIR_ALLOC_N(params, nparams) < 0)
+ return PyErr_NoMemory();
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, params, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ ret = VIR_PY_INT_FAIL;
+ goto cleanup;
+ }
+
+ new_params = setPyVirTypedParameter(info, params, nparams);
+ if (!new_params)
+ goto cleanup;
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainSetInterfaceParameters(domain, device, new_params, size, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ ret = VIR_PY_INT_FAIL;
+ goto cleanup;
+ }
+
+ ret = VIR_PY_INT_SUCCESS;
+
+cleanup:
+ virTypedParameterArrayClear(params, nparams);
+ VIR_FREE(params);
+ VIR_FREE(new_params);
+ return ret;
+}
+
+static PyObject *
+libvirt_virDomainGetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain;
+ PyObject *ret = NULL;
+ int i_retval;
+ int nparams = 0;
+ unsigned int flags;
+ const char *device = NULL;
+ virTypedParameterPtr params;
+
+ if (!PyArg_ParseTuple(args, (char *)"Ozi:virDomainGetInterfaceParameters",
+ &pyobj_domain, &device, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, NULL, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ return VIR_PY_NONE;
+
+ if (!nparams)
+ return PyDict_New();
+
+ if (VIR_ALLOC_N(params, nparams) < 0)
+ return PyErr_NoMemory();
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetInterfaceParameters(domain, device, params, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ ret = VIR_PY_NONE;
+ goto cleanup;
+ }
+
+ ret = getPyVirTypedParameter(params, nparams);
+
+cleanup:
+ virTypedParameterArrayClear(params, nparams);
+ VIR_FREE(params);
+ return ret;
+}
+
+static PyObject *
libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) {
virDomainPtr domain;
@@ -5256,6 +5380,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virDomainGetMemoryParameters", libvirt_virDomainGetMemoryParameters, METH_VARARGS, NULL},
{(char *) "virDomainSetNumaParameters", libvirt_virDomainSetNumaParameters, METH_VARARGS, NULL},
{(char *) "virDomainGetNumaParameters", libvirt_virDomainGetNumaParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainSetInterfaceParameters", libvirt_virDomainSetInterfaceParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainGetInterfaceParameters", libvirt_virDomainGetInterfaceParameters, METH_VARARGS, NULL},
{(char *) "virDomainGetVcpus", libvirt_virDomainGetVcpus, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpuFlags", libvirt_virDomainPinVcpuFlags, METH_VARARGS, NULL},
--
1.7.1
12 years, 8 months
[libvirt] [PATCH] Improve error reporting when virsh console is run without a TTY
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
If attempting to run
ssh root@somehost virsh console someguest
You'll get an error
2012-02-15 13:11:47.683+0000: 4765: info : libvirt version: 0.9.10, package: 1.fc18 (Unknown, 2012-02-15-11:48:57, lettuce.camlab.fab.redhat.com)
2012-02-15 13:11:47.683+0000: 4765: error : vshRunConsole:320 : unable to get tty attributes: Invalid argument
Connected to domain f16x86_64
Escape character is ^]
There are several problems here
- The actual error message is bad for users
- We shouldn't rely on VIR_ERROR for this case
- The prompt makes it look like we still connected
because we didn't flush stdout.
* virsh.c: Flush stdout before starting console and check
for a valid tty
---
tools/virsh.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 66ba61c..d4d3a83 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -838,8 +838,14 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, const char *name)
goto cleanup;
}
+ if (!isatty(STDIN_FILENO)) {
+ vshError(ctl, "%s", _("Cannot run interactive console without a controlling TTY"));
+ goto cleanup;
+ }
+
vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar);
+ fflush(stdout);
if (vshRunConsole(dom, name, ctl->escapeChar) == 0)
ret = true;
--
1.7.7.6
12 years, 8 months
[libvirt] [PATCH] Make virInitialize be called in multithreading environment
by Guannan Ren
When initializing libvirt shared library, calling virOnce
to make load hypervisor drivers and create thread local key
only once.
---
src/libvirt.c | 131 +++++++++++++++++++------------------------
src/util/threads-pthread.c | 8 ++-
2 files changed, 64 insertions(+), 75 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index a55d823..4656779 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -106,7 +106,8 @@ static int virNWFilterDriverTabCount = 0;
static virStateDriverPtr virStateDriverTab[MAX_DRIVERS];
static int virStateDriverTabCount = 0;
#endif
-static int initialized = 0;
+static int virInitResult = 0;
+static virOnceControl virOnceKey = VIR_ONCE_CONTROL_INITIALIZER;
#if defined(POLKIT_AUTH)
static int virConnectAuthGainPolkit(const char *privilege) {
@@ -379,30 +380,19 @@ static struct gcry_thread_cbs virTLSThreadImpl = {
} while (0)
/**
- * virInitialize:
- *
- * Initialize the library. It's better to call this routine at startup
- * in multithreaded applications to avoid potential race when initializing
- * the library.
- *
- * Calling virInitialize is mandatory, unless your first API call is one of
- * virConnectOpen*.
- *
- * Returns 0 in case of success, -1 in case of error
+ * Initialize global variable and load supported
+ * hypervisor drivers once.
*/
-int
-virInitialize(void)
+static void
+virInitializeOnce(void)
{
- if (initialized)
- return 0;
-
- initialized = 1;
+ if (virInitResult < 0)
+ return;
- if (virThreadInitialize() < 0 ||
- virErrorInitialize() < 0 ||
+ if (virErrorInitialize() < 0 ||
virRandomInitialize(time(NULL) ^ getpid()) ||
virNodeSuspendInit() < 0)
- return -1;
+ goto failed;
gcry_control(GCRYCTL_SET_THREAD_CBS, &virTLSThreadImpl);
gcry_check_version(NULL);
@@ -414,12 +404,9 @@ virInitialize(void)
VIR_DEBUG("register drivers");
#if HAVE_WINSOCK2_H
- if (winsock_init () == -1) return -1;
+ if (winsock_init () == -1) goto failed;
#endif
- if (!bindtextdomain(PACKAGE, LOCALEDIR))
- return -1;
-
/*
* Note that the order is important: the first ones have a higher
* priority when calling virConnectOpen.
@@ -459,36 +446,65 @@ virInitialize(void)
# endif
#else
# ifdef WITH_TEST
- if (testRegister() == -1) return -1;
+ if (testRegister() == -1) goto failed;
# endif
# ifdef WITH_XEN
- if (xenRegister () == -1) return -1;
+ if (xenRegister () == -1) goto failed;
# endif
# ifdef WITH_OPENVZ
- if (openvzRegister() == -1) return -1;
+ if (openvzRegister() == -1) goto failed;
# endif
# ifdef WITH_VMWARE
- if (vmwareRegister() == -1) return -1;
+ if (vmwareRegister() == -1) goto failed;
# endif
# ifdef WITH_PHYP
- if (phypRegister() == -1) return -1;
+ if (phypRegister() == -1) goto failed;
# endif
# ifdef WITH_VBOX
- if (vboxRegister() == -1) return -1;
+ if (vboxRegister() == -1) goto failed;
# endif
# ifdef WITH_ESX
- if (esxRegister() == -1) return -1;
+ if (esxRegister() == -1) goto failed;
# endif
# ifdef WITH_HYPERV
- if (hypervRegister() == -1) return -1;
+ if (hypervRegister() == -1) goto failed;
# endif
# ifdef WITH_XENAPI
- if (xenapiRegister() == -1) return -1;
+ if (xenapiRegister() == -1) goto failed;
# endif
# ifdef WITH_REMOTE
- if (remoteRegister () == -1) return -1;
+ if (remoteRegister () == -1) goto failed;
# endif
#endif
+ return;
+
+failed:
+ virInitResult = -1;
+}
+
+/**
+ * virInitialize:
+ *
+ * Initialize the library. It could be either called directly
+ * or be called via one of virConnectOpen* in multithreaded
+ * applications.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+virInitialize(void)
+{
+ int ret;
+
+ if (virThreadInitialize() < 0)
+ return -1;
+
+ if (!bindtextdomain(PACKAGE, LOCALEDIR))
+ return -1;
+
+ ret = virOnce(&virOnceKey, virInitializeOnce);
+ if (ret < 0 || virInitResult < 0)
+ return -1;
return 0;
}
@@ -573,9 +589,6 @@ DllMain (HINSTANCE instance ATTRIBUTE_UNUSED,
int
virRegisterNetworkDriver(virNetworkDriverPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -606,9 +619,6 @@ virRegisterNetworkDriver(virNetworkDriverPtr driver)
int
virRegisterInterfaceDriver(virInterfaceDriverPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -639,9 +649,6 @@ virRegisterInterfaceDriver(virInterfaceDriverPtr driver)
int
virRegisterStorageDriver(virStorageDriverPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -672,9 +679,6 @@ virRegisterStorageDriver(virStorageDriverPtr driver)
int
virRegisterDeviceMonitor(virDeviceMonitorPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -705,9 +709,6 @@ virRegisterDeviceMonitor(virDeviceMonitorPtr driver)
int
virRegisterSecretDriver(virSecretDriverPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -738,9 +739,6 @@ virRegisterSecretDriver(virSecretDriverPtr driver)
int
virRegisterNWFilterDriver(virNWFilterDriverPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -774,9 +772,6 @@ virRegisterDriver(virDriverPtr driver)
{
VIR_DEBUG("driver=%p name=%s", driver, driver ? NULLSTR(driver->name) : "(null)");
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -814,9 +809,6 @@ virRegisterDriver(virDriverPtr driver)
int
virRegisterStateDriver(virStateDriverPtr driver)
{
- if (virInitialize() < 0)
- return -1;
-
if (driver == NULL) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
@@ -844,9 +836,6 @@ virRegisterStateDriver(virStateDriverPtr driver)
int virStateInitialize(int privileged) {
int i, ret = 0;
- if (virInitialize() < 0)
- return -1;
-
for (i = 0 ; i < virStateDriverTabCount ; i++) {
if (virStateDriverTab[i]->initialize &&
virStateDriverTab[i]->initialize(privileged) < 0) {
@@ -942,9 +931,8 @@ virGetVersion(unsigned long *libVer, const char *type ATTRIBUTE_UNUSED,
{
VIR_DEBUG("libVir=%p, type=%s, typeVer=%p", libVer, type, typeVer);
- if (!initialized)
- if (virInitialize() < 0)
- goto error;
+ if (virInitialize() < 0)
+ goto error;
if (libVer == NULL)
goto error;
@@ -1342,9 +1330,8 @@ virConnectPtr
virConnectOpen (const char *name)
{
virConnectPtr ret = NULL;
- if (!initialized)
- if (virInitialize() < 0)
- goto error;
+ if (virInitialize() < 0)
+ goto error;
VIR_DEBUG("name=%s", name);
ret = do_open (name, NULL, 0);
@@ -1376,9 +1363,8 @@ virConnectPtr
virConnectOpenReadOnly(const char *name)
{
virConnectPtr ret = NULL;
- if (!initialized)
- if (virInitialize() < 0)
- goto error;
+ if (virInitialize() < 0)
+ goto error;
VIR_DEBUG("name=%s", name);
ret = do_open (name, NULL, VIR_CONNECT_RO);
@@ -1414,9 +1400,8 @@ virConnectOpenAuth(const char *name,
unsigned int flags)
{
virConnectPtr ret = NULL;
- if (!initialized)
- if (virInitialize() < 0)
- goto error;
+ if (virInitialize() < 0)
+ goto error;
VIR_DEBUG("name=%s, auth=%p, flags=%x", NULLSTR(name), auth, flags);
ret = do_open (name, auth, flags);
diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c
index ea64887..15d1407 100644
--- a/src/util/threads-pthread.c
+++ b/src/util/threads-pthread.c
@@ -42,10 +42,14 @@ void virThreadOnExit(void)
int virOnce(virOnceControlPtr once, virOnceFunc init)
{
- return pthread_once(&once->once, init);
+ int ret;
+ if ((ret = pthread_once(&once->once, init)) != 0) {
+ errno = ret;
+ return -1;
+ }
+ return 0;
}
-
int virMutexInit(virMutexPtr m)
{
int ret;
--
1.7.7.5
12 years, 8 months