[libvirt] [PATCH] spec: Fix dependency for lock-sanlock subpackage
by Jiri Denemark
This should not make a big difference in real world since libvirt-daemon,
which is already required by libvirt-lock-sanlock, requires
libvirt-client and thus libvirt-lock-sanlock gets this dependency
transitively. However, since libvirt-lock-sanlock contains
sanlock_helper binary linked to libvirt.so, we should start requiring
libvirt-client directly.
---
libvirt.spec.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 2f3e829..511949e 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1029,24 +1029,25 @@ Include header files & development libraries for the libvirt C library.
%if %{with_sanlock}
%package lock-sanlock
Summary: Sanlock lock manager plugin for QEMU driver
Group: Development/Libraries
%if 0%{?fedora} >= 17 || 0%{?rhel} >= 6
Requires: sanlock >= 2.4
%else
Requires: sanlock >= 1.8
%endif
#for virt-sanlock-cleanup require augeas
Requires: augeas
Requires: %{name}-daemon = %{version}-%{release}
+Requires: %{name}-client = %{version}-%{release}
%description lock-sanlock
Includes the Sanlock lock manager plugin for the QEMU
driver
%endif
%if %{with_python}
%package python
Summary: Python bindings for the libvirt library
Group: Development/Libraries
Requires: %{name}-client = %{version}-%{release}
--
1.7.12.3
12 years, 1 month
[libvirt] [PATCH 0/3] Add support for HyperV Enlightenment features
by Peter Krempa
This series adds framework to deal with various HyperV Enlightenment
features that improve behavior of Microsoft Windows guests.
First of the features implemented is "relaxed" that changes
the behavior of timers.
The series is designed to ease addition of other hyperv features in the
future.
Peter Krempa (3):
conf: Make tri-state feature options more universal
conf: Add support for HyperV Enlightenment features
qemu: Add support for HyperV Enlightenment feature "relaxed"
docs/formatdomain.html.in | 21 +++++++
docs/schemas/domaincommon.rng | 28 ++++++++-
src/conf/domain_conf.c | 80 +++++++++++++++++++++++--
src/conf/domain_conf.h | 24 +++++---
src/libvirt_private.syms | 6 +-
src/qemu/qemu_command.c | 44 +++++++++++++-
tests/qemuxml2argvdata/qemuxml2argv-hyperv.args | 4 ++
tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml | 28 +++++++++
tests/qemuxml2argvtest.c | 2 +
tests/qemuxml2xmltest.c | 2 +
10 files changed, 221 insertions(+), 18 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hyperv.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hyperv.xml
--
1.7.12.3
12 years, 1 month
[libvirt] [PATCH] qemu: Correctly wait for spice to migrate
by Michal Privoznik
Currently we query-spice after the main migration has completed
before moving to next state. Qemu reports this as boolean (not
enclosed within quotes). Therefore it is not correct to use
virJSONValueObjectGetString but virJSONValueObjectGetBoolean instead.
---
Meanwhile, this is does no harm for now, since we fail to set
QEMU_CAPS_SEAMLESS_MIGRATION as we use querying capabilities on
the QMP monitor where 'seamless-migration=[on|off]' cmd line
option is not advertised. However, on some distros where we still
compute capabilities by parsing '-help' output we fail.
src/qemu/qemu_monitor_json.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 2daf8ea..8087e4f 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2399,7 +2399,6 @@ qemuMonitorJSONSpiceGetMigrationStatusReply(virJSONValuePtr reply,
bool *spice_migrated)
{
virJSONValuePtr ret;
- const char *migrated_str;
if (!(ret = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2407,13 +2406,11 @@ qemuMonitorJSONSpiceGetMigrationStatusReply(virJSONValuePtr reply,
return -1;
}
- if (!(migrated_str = virJSONValueObjectGetString(ret, "migrated"))) {
+ if (virJSONValueObjectGetBoolean(ret, "migrated", spice_migrated) < 0) {
/* Deliberately don't report error here as we are
* probably dealing with older qemu which doesn't
* report this yet. Pretend spice is migrated. */
*spice_migrated = true;
- } else {
- *spice_migrated = STREQ(migrated_str, "true");
}
return 0;
--
1.7.8.6
12 years, 1 month
[libvirt] [PATCH] qemu: Fixed default machine detection in qemuCapsParseMachineTypesStr
by Viktor Mihajlovski
The machine in the last output line of <qemu-binary> -M ?
was always reported as default machine even if this wasn't the
actual default. Trivial fix.
Signed-off-by: Viktor Mihajlovski <mihajlov(a)linux.vnet.ibm.com>
---
src/qemu/qemu_capabilities.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index fb0fe54..985d4de 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -284,7 +284,7 @@ qemuCapsParseMachineTypesStr(const char *output,
goto no_memory;
p = t;
- if (!(t = strstr(p, "(default)")) && (!next || t < next))
+ if ((t = strstr(p, "(default)")) && (!next || t < next))
defIdx = caps->nmachineTypes;
if ((t = strstr(p, "(alias of ")) && (!next || t < next)) {
--
1.7.0.4
12 years, 1 month
[libvirt] [PATCH 1/2] selinux: fix wrong tapfd relablling
by Guannan Ren
It should relabel tapfd of virtual network of type VIR_DOMAIN_NET_TYPE_DIRECT
rather than VIR_DOMAIN_NET_TYPE_NETWORK and VIR_DOMAIN_NET_TYPE_BRIDGE
(commit ae368ebfcc4923d0b32e83d4ca96a6f599625785 introduced this bug)
---
src/qemu/qemu_command.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 239592c..0c0c400 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5412,10 +5412,6 @@ qemuBuildCommandLine(virConnectPtr conn,
if (tapfd < 0)
goto error;
- if (virSecurityManagerSetTapFDLabel(driver->securityManager,
- def, tapfd) < 0)
- goto error;
-
last_good_net = i;
virCommandTransferFD(cmd, tapfd);
@@ -5429,6 +5425,10 @@ qemuBuildCommandLine(virConnectPtr conn,
if (tapfd < 0)
goto error;
+ if (virSecurityManagerSetTapFDLabel(driver->securityManager,
+ def, tapfd) < 0)
+ goto error;
+
last_good_net = i;
virCommandTransferFD(cmd, tapfd);
--
1.7.11.2
12 years, 1 month
[libvirt] [PATCH 2/3] Add a "forward family" option
by Benjamin Cama
It allows to specify forwarding only for IPv4 or IPv6. Not specifying it
enables forwarding for both protocols.
---
src/conf/network_conf.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++-
src/conf/network_conf.h | 1 +
2 files changed, 58 insertions(+), 1 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 891d48c..8c2ae9b 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1204,6 +1204,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
xmlNodePtr virtPortNode = NULL;
xmlNodePtr forwardNode = NULL;
int nIps, nPortGroups, nForwardIfs, nForwardPfs, nForwardAddrs;
+ char *forwardFamily = NULL;
char *forwardDev = NULL;
char *forwardManaged = NULL;
char *type = NULL;
@@ -1358,6 +1359,23 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->forwardType = VIR_NETWORK_FORWARD_NAT;
}
+ forwardFamily = virXPathString("string(./@family)", ctxt);
+ if (forwardFamily) {
+ if (STREQ(forwardFamily, "ipv4")) {
+ def->forwardFamily = AF_INET;
+ } else if (STREQ(forwardFamily, "ipv6")) {
+ def->forwardFamily = AF_INET6;
+ } else {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("Unknown forward family '%s'"), forwardFamily);
+ VIR_FREE(forwardFamily);
+ goto error;
+ }
+ VIR_FREE(forwardFamily);
+ } else {
+ def->forwardFamily = AF_UNSPEC;
+ }
+
forwardDev = virXPathString("string(./@dev)", ctxt);
forwardManaged = virXPathString("string(./@managed)", ctxt);
if(forwardManaged != NULL) {
@@ -1515,8 +1533,16 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
VIR_FREE(forwardIfNodes);
VIR_FREE(forwardAddrNodes);
switch (def->forwardType) {
- case VIR_NETWORK_FORWARD_ROUTE:
case VIR_NETWORK_FORWARD_NAT:
+ if (def->forwardFamily == AF_INET6) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("%s forwarding is not allowed in IPv6 (network '%s')"),
+ virNetworkForwardTypeToString(def->forwardType),
+ def->name);
+ goto error;
+ }
+ /* fall through to next case */
+ case VIR_NETWORK_FORWARD_ROUTE:
/* It's pointless to specify L3 forwarding without specifying
* the network we're on.
*/
@@ -1527,6 +1553,25 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->name);
goto error;
}
+ /* If forwarding for one family only, an address from this family
+ * must be present
+ */
+ if (def->forwardFamily) {
+ int ii;
+ for (ii = 0; ii < def->nips; ii++) {
+ if (VIR_SOCKET_ADDR_IS_FAMILY(&def->ips[ii].address, def->forwardFamily))
+ break;
+ }
+ if (ii == def->nips) {
+ char ipVersion = def->forwardFamily == AF_INET6 ? '6' : '4';
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("%s IPv%c forwarding requested, but no IPv%c address provided for network '%s'"),
+ virNetworkForwardTypeToString(def->forwardType),
+ ipVersion, ipVersion,
+ def->name);
+ goto error;
+ }
+ }
if (def->nForwardIfs > 1) {
virReportError(VIR_ERR_XML_ERROR,
_("multiple forwarding interfaces specified for network '%s', only one is supported"),
@@ -1555,6 +1600,13 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->name);
goto error;
}
+ if (def->forwardFamily) {
+ virNetworkReportError(VIR_ERR_XML_ERROR,
+ _("bridge forward family option only allowed in route and nat mode, not in %s (network '%s')"),
+ virNetworkForwardTypeToString(def->forwardType),
+ def->name);
+ goto error;
+ }
break;
}
}
@@ -1830,6 +1882,8 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
if (!def->nForwardPfs)
dev = virNetworkDefForwardIf(def, 0);
const char *mode = virNetworkForwardTypeToString(def->forwardType);
+ const char *family = (def->forwardFamily == AF_INET ? "ipv4" :
+ def->forwardFamily == AF_INET6 ? "ipv6" : NULL);
if (!mode) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1846,6 +1900,8 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
else
virBufferAddLit(&buf, " managed='no'");
}
+ if (family)
+ virBufferEscapeString(&buf, " family='%s'", family);
virBufferAsprintf(&buf, "%s>\n",
(def->nForwardIfs || def->nForwardPfs) ? "" : "/");
virBufferAdjustIndent(&buf, 2);
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 55502fb..61ecbc1 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -186,6 +186,7 @@ struct _virNetworkDef {
int forwardType; /* One of virNetworkForwardType constants */
int managed; /* managed attribute for hostdev mode */
+ int forwardFamily; /* AF_INET or AF_INET6 - AF_UNSPEC for both */
/* If there are multiple forward devices (i.e. a pool of
* interfaces), they will be listed here.
--
1.7.2.5
12 years, 1 month
[libvirt] [PATCH 1/3] Only check for IP forwarding, do not enable it
by Benjamin Cama
Enabling IP forwarding without the administrator's consent is bad. Only
check for forwarding, do not enable it.
---
src/network/bridge_driver.c | 56 +++++++++++++++++++++++++++++++++----------
1 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index e1846ee..e3e8dc2 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1853,19 +1853,51 @@ networkReloadIptablesRules(struct network_driver *driver)
}
}
-/* Enable IP Forwarding. Return 0 for success, -1 for failure. */
+#define SYSCTL_PATH "/proc/sys"
+
+/* Check for IP Forwarding. Return 0 if required family is enabled, -1 for failure. */
static int
-networkEnableIpForwarding(bool enableIPv4, bool enableIPv6)
+networkCheckIpForwarding(bool checkIPv4, bool checkIPv6)
{
int ret = 0;
- if (enableIPv4)
- ret = virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n", 0);
- if (enableIPv6 && ret == 0)
- ret = virFileWriteStr("/proc/sys/net/ipv6/conf/all/forwarding", "1\n", 0);
- return ret;
-}
+ char *buf = NULL;
-#define SYSCTL_PATH "/proc/sys"
+ if (checkIPv4) {
+ ret = virFileReadAll(SYSCTL_PATH "/net/ipv4/ip_forward", 2, &buf);
+ if (ret != 2)
+ goto error;
+ if (STRNEQ(buf, "1\n")) {
+ networkReportError(VIR_ERR_SYSTEM_ERROR,
+ _("IP forwarding is not enabled on your system"));
+ goto cleanup;
+ }
+ }
+ if (checkIPv6) {
+ if (ret > 0)
+ VIR_FREE(buf);
+ ret = virFileReadAll(SYSCTL_PATH "/net/ipv6/conf/all/forwarding", 2, &buf);
+ if (ret != 2)
+ goto error;
+ if (STRNEQ(buf, "1\n")) {
+ networkReportError(VIR_ERR_SYSTEM_ERROR,
+ _("IPv6 forwarding is not enabled on your system"));
+ goto cleanup;
+ }
+ }
+
+ VIR_FREE(buf);
+ return 0;
+
+error:
+ virReportSystemError(errno, "%s", _("cannot check for IP forwarding"));
+cleanup:
+ if (ret > 0) {
+ VIR_FREE(buf);
+ return -1;
+ } else {
+ return ret;
+ }
+}
static int
networkSetIPv6Sysctls(virNetworkObjPtr network)
@@ -2140,11 +2172,9 @@ networkStartNetworkVirtual(struct network_driver *driver,
if (virNetDevSetOnline(network->def->bridge, 1) < 0)
goto err2;
- /* If forwardType != NONE, turn on global IP forwarding */
+ /* If forwardType != NONE, check for IP forwarding */
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
- networkEnableIpForwarding(v4present, v6present) < 0) {
- virReportSystemError(errno, "%s",
- _("failed to enable IP forwarding"));
+ networkCheckIpForwarding(v4present, v6present) < 0) {
goto err3;
}
--
1.7.2.5
12 years, 1 month
[libvirt] [PATCH] qemu: Clear async job when p2p migration fails early
by Jiri Denemark
When p2p migration fails early because qemuMigrationIsAllowed or
qemuMigrationIsSafe say migration should be cancelled, we fail to clear
the migration-out async job. As a result of that, further APIs called
for the same domain may fail with Timed out during operation: cannot
acquire state change lock.
Reported by Guido Winkelmann.
---
src/qemu/qemu_migration.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 68d614d..65cd6ec 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2641,10 +2641,10 @@ qemuMigrationPerformJob(struct qemud_driver *driver,
}
if (!qemuMigrationIsAllowed(driver, vm, NULL))
- goto cleanup;
+ goto endjob;
if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
- goto cleanup;
+ goto endjob;
resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING;
--
1.7.12.3
12 years, 1 month
[libvirt] [PATCH] interface: add virInterfaceGetXMLDesc() in udev
by Doug Goldstein
Added support for retrieving the XML defining a specific interface via
the udev based backend to virInterface. Implement the following APIs
for the udev based backend:
* virInterfaceGetXMLDesc()
Note: Does not support bond devices.
---
src/interface/interface_backend_udev.c | 251 ++++++++++++++++++++++++++++++++
1 files changed, 251 insertions(+), 0 deletions(-)
diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c
index 1cb6dfe..370f64a 100644
--- a/src/interface/interface_backend_udev.c
+++ b/src/interface/interface_backend_udev.c
@@ -19,6 +19,8 @@
*/
#include <config.h>
+#include <errno.h>
+#include <dirent.h>
#include <libudev.h>
#include "virterror_internal.h"
@@ -489,6 +491,254 @@ err:
return ret;
}
+/**
+ * Helper function for our use of scandir()
+ *
+ * @param entry - directory entry passed by scandir()
+ *
+ * @return 1 if we want to add it to scandir's list, 0 if not.
+ */
+static int
+udevIfaceScanDirFilter(const struct dirent *entry)
+{
+ if (STREQ(entry->d_name, ".") || STREQ(entry->d_name, ".."))
+ return 0;
+
+ return 1;
+}
+
+/**
+ * Frees any memory allocated by udevIfaceGetIfaceDef()
+ *
+ * @param ifacedef - interface to free and cleanup
+ */
+static void
+udevIfaceFreeIfaceDef(virInterfaceDef *ifacedef)
+{
+ if (!ifacedef)
+ return;
+
+ if (ifacedef->type == VIR_INTERFACE_TYPE_BRIDGE) {
+ VIR_FREE(ifacedef->data.bridge.delay);
+ for (int i = 0; i < ifacedef->data.bridge.nbItf; i++) {
+ VIR_FREE(ifacedef->data.bridge.itf[i]);
+ }
+ VIR_FREE(ifacedef->data.bridge.itf);
+ }
+
+ if (ifacedef->type == VIR_INTERFACE_TYPE_VLAN) {
+ VIR_FREE(ifacedef->data.vlan.devname);
+ }
+
+ VIR_FREE(ifacedef->mac);
+ VIR_FREE(ifacedef->name);
+
+ VIR_FREE(ifacedef);
+}
+
+
+static virInterfaceDef * ATTRIBUTE_NONNULL(1)
+udevIfaceGetIfaceDef(struct udev *udev, char *name)
+{
+ struct udev_device *dev;
+ virInterfaceDef *ifacedef;
+ unsigned int mtu;
+ const char *mtu_str;
+ char *vlan_parent_dev = NULL;
+ struct dirent **member_list = NULL;
+ int member_count = 0;
+
+ /* Allocate our interface definition structure */
+ if (VIR_ALLOC(ifacedef) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ /* Clear our structure and set safe defaults */
+ memset(ifacedef, 0, sizeof(ifacedef));
+ ifacedef->startmode = VIR_INTERFACE_START_UNSPECIFIED;
+ ifacedef->type = VIR_INTERFACE_TYPE_ETHERNET;
+ ifacedef->name = strdup(name);
+
+ if (!ifacedef->name) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Lookup the device we've been asked about */
+ dev = udev_device_new_from_subsystem_sysname(udev, "net", name);
+ if (!dev) {
+ virReportError(VIR_ERR_NO_INTERFACE,
+ _("couldn't find interface named '%s'"), name);
+ goto cleanup;
+ }
+
+ /* MAC address */
+ ifacedef->mac = strdup(udev_device_get_sysattr_value(dev, "address"));
+ if (!ifacedef) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* MTU */
+ mtu_str = udev_device_get_sysattr_value(dev, "mtu");
+ if (virStrToLong_ui(mtu_str, NULL, 10, &mtu) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse MTU value '%s'"), mtu_str);
+ goto cleanup;
+ }
+ ifacedef->mtu = mtu;
+
+ /* Number of IP protocols this interface has assigned */
+ /* XXX: Do we want a netlink query or a call out to ip or leave it? */
+ ifacedef->nprotos = 0;
+ ifacedef->protos = NULL;
+
+ /* Check if its a VLAN since we can have a VLAN of any of the
+ * other devices */
+ vlan_parent_dev = strrchr(name, '.');
+ if (vlan_parent_dev) {
+ /* Found the VLAN dot */
+ char *vid;
+
+ vlan_parent_dev = strdup(name);
+ if (!vlan_parent_dev) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Find the DEVICE.VID separator again */
+ vid = strrchr(vlan_parent_dev, '.');
+ if (!vid) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to find the VID for the VLAN device '%s'"),
+ name);
+ goto cleanup;
+ }
+
+ /* Replace the dot with a NULL so we can have the device and VID */
+ vid[0] = '\0';
+ vid++;
+
+ /* Set our type to VLAN */
+ ifacedef->type = VIR_INTERFACE_TYPE_VLAN;
+
+ /* Set the VLAN specifics */
+ ifacedef->data.vlan.tag = vid;
+ ifacedef->data.vlan.devname = vlan_parent_dev;
+ } else if (STREQ_NULLABLE(udev_device_get_devtype(dev), "bridge")) {
+ /* Check if its a bridge device */
+ char *member_path;
+ const char *stp_str;
+ int stp;
+
+ /* Set our type to Bridge */
+ ifacedef->type = VIR_INTERFACE_TYPE_BRIDGE;
+
+ /* Bridge specifics */
+ ifacedef->data.bridge.delay =
+ strdup(udev_device_get_sysattr_value(dev, "bridge/forward_delay"));
+ if (!ifacedef->data.bridge.delay) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ stp_str = udev_device_get_sysattr_value(dev, "bridge/stp_state");
+ if (virStrToLong_i(stp_str, NULL, 10, &stp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse STP state '%s'"), stp_str);
+ goto cleanup;
+ }
+ ifacedef->data.bridge.stp = stp;
+
+ /* Members of the bridge */
+ virAsprintf(&member_path, "%s/%s",
+ udev_device_get_syspath(dev), "brif");
+ if (!member_path) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Get each member of the bridge */
+ member_count = scandir(member_path, &member_list,
+ udevIfaceScanDirFilter, alphasort);
+
+ /* Don't need the path anymore */
+ VIR_FREE(member_path);
+
+ if (member_count < 0) {
+ virReportSystemError(errno,
+ _("Could not get members of bridge '%s'"),
+ name);
+ goto cleanup;
+ }
+
+ /* Allocate our list of member devices */
+ if (VIR_ALLOC_N(ifacedef->data.bridge.itf, member_count) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ ifacedef->data.bridge.nbItf = member_count;
+
+ for (int i= 0; i < member_count; i++) {
+ ifacedef->data.bridge.itf[i] =
+ udevIfaceGetIfaceDef(udev, member_list[i]->d_name);
+ VIR_FREE(member_list[i]);
+ }
+
+ VIR_FREE(member_list);
+
+ } else {
+ /* Set our type to ethernet */
+ ifacedef->type = VIR_INTERFACE_TYPE_ETHERNET;
+ }
+
+ return ifacedef;
+
+cleanup:
+ for (int i = 0; i < member_count; i++) {
+ VIR_FREE(member_list[i]);
+ }
+ VIR_FREE(member_list);
+
+ udevIfaceFreeIfaceDef(ifacedef);
+
+ return NULL;
+}
+
+static char *
+udevIfaceGetXMLDesc(virInterfacePtr ifinfo,
+ unsigned int flags)
+{
+ struct udev_iface_driver *driverState = ifinfo->conn->interfacePrivateData;
+ struct udev *udev = udev_ref(driverState->udev);
+ virInterfaceDef *ifacedef;
+ char *xmlstr = NULL;
+
+ virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL);
+
+ /* Recursively build up the interface XML based on the requested
+ * interface name
+ */
+ ifacedef = udevIfaceGetIfaceDef(udev, ifinfo->name);
+
+ /* We've already printed by it happened */
+ if (!ifacedef)
+ goto err;
+
+ /* Convert our interface to XML */
+ xmlstr = virInterfaceDefFormat(ifacedef);
+
+ /* Recursively free our interface structures and free the children too */
+ udevIfaceFreeIfaceDef(ifacedef);
+
+err:
+ /* decrement our udev ptr */
+ udev_unref(udev);
+
+ return xmlstr;
+}
+
static int
udevIfaceIsActive(virInterfacePtr ifinfo)
{
@@ -529,6 +779,7 @@ static virInterfaceDriver udevIfaceDriver = {
.listAllInterfaces = udevIfaceListAllInterfaces, /* 0.10.3 */
.interfaceLookupByName = udevIfaceLookupByName, /* 0.10.3 */
.interfaceLookupByMACString = udevIfaceLookupByMACString, /* 0.10.3 */
+ .interfaceGetXMLDesc = udevIfaceGetXMLDesc, /* 0.10.3 */
.interfaceIsActive = udevIfaceIsActive, /* 0.10.3 */
};
--
1.7.8.6
12 years, 1 month