[libvirt] [PATCH 0/4] admin: Fix a leaking conn reference and other improvements
by Erik Skultety
This series fixes a memory leak in a dangling conn object reference caused by
assigning NULL to conn->closeCallback object by the RPC catch-disconnect routine
followed by a comparison of equality of conn->closeCallback->callback and the
client-registered callback reference.
Before fixing the issue itself, there are some new helpers introduced following
the same idea as the helpers introduced by series
https://www.redhat.com/archives/libvir-list/2016-February/msg00849.html
Erik Skultety (4):
vsh: Drop conditional error reporting in vshErrorHandler
admin: Remove unnecessary @conn object locking
datatypes: Introduce some admin-related close callback handling
helpers
admin: Use the newly introduced close callback handling helpers
po/POTFILES.in | 1 +
src/admin/admin_remote.c | 6 +---
src/datatypes.c | 67 +++++++++++++++++++++++++++++++++++++++---
src/datatypes.h | 8 +++++
src/libvirt-admin.c | 24 +--------------
src/libvirt_admin_private.syms | 3 ++
tools/vsh.c | 2 --
7 files changed, 77 insertions(+), 34 deletions(-)
--
2.5.5
8 years, 1 month
[libvirt] [PATCH] storage_backend_rbd: check the return value of rados_conf_set
by Chen Hanxiao
From: Chen Hanxiao <chenhanxiao(a)gmail.com>
We forget to check the return value of rados_conf_set.
Signed-off-by: Chen Hanxiao <chenhanxiao(a)gmail.com>
---
src/storage/storage_backend_rbd.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index 718c4d6..58bcb9a 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -162,10 +162,20 @@ virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
rados_conf_set(ptr->cluster, "client_mount_timeout", client_mount_timeout);
VIR_DEBUG("Setting RADOS option rados_mon_op_timeout to %s", mon_op_timeout);
- rados_conf_set(ptr->cluster, "rados_mon_op_timeout", mon_op_timeout);
+ if (rados_conf_set(ptr->cluster, "rados_mon_op_timeout", mon_op_timeout) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to set RADOS option: %s"),
+ "rados_mon_op_timeout");
+ goto cleanup;
+ }
VIR_DEBUG("Setting RADOS option rados_osd_op_timeout to %s", osd_op_timeout);
- rados_conf_set(ptr->cluster, "rados_osd_op_timeout", osd_op_timeout);
+ if (rados_conf_set(ptr->cluster, "rados_osd_op_timeout", osd_op_timeout) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to set RADOS option: %s"),
+ "rados_osd_op_timeout");
+ goto cleanup;
+ }
/*
* Librbd supports creating RBD format 2 images. We no longer have to invoke
@@ -173,7 +183,12 @@ virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
* This leaves us to simply use rbd_create() and use the default behavior of librbd
*/
VIR_DEBUG("Setting RADOS option rbd_default_format to %s", rbd_default_format);
- rados_conf_set(ptr->cluster, "rbd_default_format", rbd_default_format);
+ if (rados_conf_set(ptr->cluster, "rbd_default_format", rbd_default_format) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to set RADOS option: %s"),
+ "rbd_default_format");
+ goto cleanup;
+ }
ptr->starttime = time(0);
if ((r = rados_connect(ptr->cluster)) < 0) {
--
1.8.3.1
8 years, 1 month
[libvirt] How to make udev not touch my device?
by Michal Privoznik
Hey udev developers,
I'm a libvirt developer and I've been facing an interesting issue
recently. Libvirt is a library for managing virtual machines and as such
allows basically any device to be exposed to a virtual machine. For
instance, a virtual machine can use /dev/sdX as its own disk. Because of
security reasons we allow users to configure their VMs to run under
different UID/GID and also SELinux context. That means that whenever a
VM is being started up, libvirtd (our daemon we have) relabels all the
necessary paths that QEMU process (representing VM) can touch.
However, I'm facing an issue that I don't know how to fix. In some cases
QEMU can close & reopen a block device. However, closing a block device
triggers an event and hence if there is a rule that sets a security
label on a device the QEMU process is unable to reopen the device again.
My question is, whet we can do to prevent udev from mangling with our
security labels that we've set on the devices?
One of the ideas our lead developer had was for libvirt to set some kind
of udev label on devices managed by libvirt (when setting up security
labels) and then whenever udev sees such labelled device it won't touch
it at all (this could be achieved by a rule perhaps?). Later, when
domain is shutting down libvirt removes that label. But I don't think
setting an arbitrary label on devices is supported, is it?
Michal
8 years, 1 month
[libvirt] [PATCH] docs: change "Learn" to "Documentation"
by Pavel Hrdina
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
I know that this is not a big issue, but I don't like the "Learn". As I've
mentioned in my review [1] IMO "Documentation" is better.
[1] <https://www.redhat.com/archives/libvir-list/2016-November/msg00446.html>
docs/page.xsl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/page.xsl b/docs/page.xsl
index fcb5191..837060b 100644
--- a/docs/page.xsl
+++ b/docs/page.xsl
@@ -106,7 +106,7 @@
<ul>
<li><a href="downloads.html">Download</a></li>
<li><a href="contribute.html">Contribute</a></li>
- <li><a href="docs.html">Learn</a></li>
+ <li><a href="docs.html">Documentation</a></li>
</ul>
</div>
<div id="search">
--
2.10.2
8 years, 1 month
[libvirt] [PATCH] qemuDomainAttachNetDevice: Avoid @originalError leak
by Michal Privoznik
Coverity identified that this variable might be leaked. And it's
right. If an error occurred and we have to roll back the control
jumps to try_remove label where we save the current error (see
0e82fa4c34 for more info). However, inside the code a jump onto
other label is possible thus leaking the error object.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Best viewed with 'git show --ignore-space-change'
src/qemu/qemu_hotplug.c | 42 +++++++++++++++++++++---------------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1bc2706..0dcbee6 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1326,32 +1326,32 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
if (vlan < 0) {
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV)) {
char *netdev_name;
- if (virAsprintf(&netdev_name, "host%s", net->info.alias) < 0)
- goto cleanup;
- qemuDomainObjEnterMonitor(driver, vm);
- if (charDevPlugged &&
- qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
- VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
- if (netdevPlugged &&
- qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
- VIR_WARN("Failed to remove network backend for netdev %s",
- netdev_name);
- ignore_value(qemuDomainObjExitMonitor(driver, vm));
- VIR_FREE(netdev_name);
+ if (virAsprintf(&netdev_name, "host%s", net->info.alias) >= 0) {
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (charDevPlugged &&
+ qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
+ VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
+ if (netdevPlugged &&
+ qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
+ VIR_WARN("Failed to remove network backend for netdev %s",
+ netdev_name);
+ ignore_value(qemuDomainObjExitMonitor(driver, vm));
+ VIR_FREE(netdev_name);
+ }
} else {
VIR_WARN("Unable to remove network backend");
}
} else {
char *hostnet_name;
- if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0)
- goto cleanup;
- qemuDomainObjEnterMonitor(driver, vm);
- if (hostPlugged &&
- qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0)
- VIR_WARN("Failed to remove network backend for vlan %d, net %s",
- vlan, hostnet_name);
- ignore_value(qemuDomainObjExitMonitor(driver, vm));
- VIR_FREE(hostnet_name);
+ if (virAsprintf(&hostnet_name, "host%s", net->info.alias) >= 0) {
+ qemuDomainObjEnterMonitor(driver, vm);
+ if (hostPlugged &&
+ qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0)
+ VIR_WARN("Failed to remove network backend for vlan %d, net %s",
+ vlan, hostnet_name);
+ ignore_value(qemuDomainObjExitMonitor(driver, vm));
+ VIR_FREE(hostnet_name);
+ }
}
virSetError(originalError);
virFreeError(originalError);
--
2.8.4
8 years, 1 month
[libvirt] [PATCH] qemu: Emit domain events for all virtio-serial channels
by Matt Broadstone
Presently domain events are emitted for the "agent lifecycle" which
is a specialization on virtio-serial events specific to the channel
named "org.qemu.guest_agent.0". This patch adds a generic event for
"channel lifecycles", which emit state change events for all
attached channels.
---
daemon/remote.c | 42 +++++++++++++++++
examples/object-events/event-test.c | 57 ++++++++++++++++++++++++
include/libvirt/libvirt-domain.h | 41 +++++++++++++++++
src/conf/domain_event.c | 89 +++++++++++++++++++++++++++++++++++++
src/conf/domain_event.h | 12 +++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_driver.c | 5 +++
src/qemu/qemu_process.c | 6 +++
src/remote/remote_driver.c | 32 +++++++++++++
src/remote/remote_protocol.x | 17 ++++++-
src/remote_protocol-structs | 7 +++
tools/virsh-domain.c | 35 +++++++++++++++
12 files changed, 344 insertions(+), 1 deletion(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index e414f92..25b32f2 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -1086,6 +1086,47 @@ remoteRelayDomainEventAgentLifecycle(virConnectPtr conn,
static int
+remoteRelayDomainEventChannelLifecycle(virConnectPtr conn,
+ virDomainPtr dom,
+ const char *channelName,
+ int state,
+ int reason,
+ void *opaque)
+{
+ daemonClientEventCallbackPtr callback = opaque;
+ remote_domain_event_callback_channel_lifecycle_msg data;
+
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+ return -1;
+
+ VIR_DEBUG("Relaying domain channel lifecycle event %s %d, callback %d, "
+ " name: %s, state %d, reason %d",
+ dom->name, dom->id, callback->callbackID, channelName, state, reason);
+
+ /* build return data */
+ memset(&data, 0, sizeof(data));
+ data.callbackID = callback->callbackID;
+ make_nonnull_domain(&data.dom, dom);
+
+ if (VIR_STRDUP(data.channelName, channelName) < 0)
+ goto error;
+ data.state = state;
+ data.reason = reason;
+
+ remoteDispatchObjectEventSend(callback->client, remoteProgram,
+ REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE,
+ (xdrproc_t)xdr_remote_domain_event_callback_channel_lifecycle_msg,
+ &data);
+
+ return 0;
+ error:
+ VIR_FREE(data.channelName);
+ return -1;
+}
+
+
+static int
remoteRelayDomainEventDeviceAdded(virConnectPtr conn,
virDomainPtr dom,
const char *devAlias,
@@ -1248,6 +1289,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMigrationIteration),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventJobCompleted),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed),
+ VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventChannelLifecycle)
};
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
diff --git a/examples/object-events/event-test.c b/examples/object-events/event-test.c
index 730cb8b..da023eb 100644
--- a/examples/object-events/event-test.c
+++ b/examples/object-events/event-test.c
@@ -337,6 +337,46 @@ guestAgentLifecycleEventReasonToString(int event)
return "unknown";
}
+
+static const char *
+guestChannelLifecycleEventStateToString(int event)
+{
+ switch ((virConnectDomainEventChannelLifecycleState) event) {
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_DISCONNECTED:
+ return "Disconnected";
+
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_CONNECTED:
+ return "Connected";
+
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_LAST:
+ break;
+ }
+
+ return "unknown";
+}
+
+
+static const char *
+guestChannelLifecycleEventReasonToString(int event)
+{
+ switch ((virConnectDomainEventChannelLifecycleReason) event) {
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_UNKNOWN:
+ return "Unknown";
+
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_DOMAIN_STARTED:
+ return "Domain started";
+
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_CHANNEL:
+ return "Channel event";
+
+ case VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_LAST:
+ break;
+ }
+
+ return "unknown";
+}
+
+
static const char *
storagePoolEventToString(int event)
{
@@ -797,6 +837,22 @@ myDomainEventAgentLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
return 0;
}
+static int
+myDomainEventChannelLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *channelName,
+ int state,
+ int reason,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ printf("%s EVENT: Domain %s(%d) guest channel(%s) state changed: %s reason: %s\n",
+ __func__, virDomainGetName(dom), virDomainGetID(dom), channelName,
+ guestChannelLifecycleEventStateToString(state),
+ guestChannelLifecycleEventReasonToString(reason));
+
+ return 0;
+}
+
static int
myDomainEventDeviceAddedCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -971,6 +1027,7 @@ struct domainEventData domainEvents[] = {
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION, myDomainEventMigrationIterationCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, myDomainEventJobCompletedCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
+ DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_CHANNEL_LIFECYCLE, myDomainEventChannelLifecycleCallback)
};
struct storagePoolEventData {
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 5f50660..d720132 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3965,6 +3965,46 @@ typedef void (*virConnectDomainEventAgentLifecycleCallback)(virConnectPtr conn,
int reason,
void *opaque);
+typedef enum {
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_CONNECTED = 1, /* channel connected */
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_DISCONNECTED = 2, /* channel disconnected */
+
+# ifdef VIR_ENUM_SENTINELS
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_LAST
+# endif
+} virConnectDomainEventChannelLifecycleState;
+
+typedef enum {
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_UNKNOWN = 0, /* unknown state change reason */
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_DOMAIN_STARTED = 1, /* state changed due to domain start */
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_CHANNEL = 2, /* channel state changed */
+
+# ifdef VIR_ENUM_SENTINELS
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_LAST
+# endif
+} virConnectDomainEventChannelLifecycleReason;
+
+/**
+ * virConnectDomainEventChannelLifecycleCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @channelName: the name of the channel on which the event occurred
+ * @state: new state of the guest channel, one of virConnectDomainEventChannelLifecycleState
+ * @reason: reason for state change; one of virConnectDomainEventChannelLifecycleReason
+ * @opaque: application specified data
+ *
+ * This callback occurs when libvirt detects a change in the state of a guest
+ * serial channel.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_CHANNEL_LIFECYCLE with virConnectDomainEventRegisterAny()
+ */
+typedef void (*virConnectDomainEventChannelLifecycleCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ const char *channelName,
+ int state,
+ int reason,
+ void *opaque);
/**
* VIR_DOMAIN_EVENT_CALLBACK:
@@ -4006,6 +4046,7 @@ typedef enum {
VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION = 20, /* virConnectDomainEventMigrationIterationCallback */
VIR_DOMAIN_EVENT_ID_JOB_COMPLETED = 21, /* virConnectDomainEventJobCompletedCallback */
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* virConnectDomainEventDeviceRemovalFailedCallback */
+ VIR_DOMAIN_EVENT_ID_CHANNEL_LIFECYCLE = 23, /* virConnectDomainEventChannelLifecycleCallback */
# ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_EVENT_ID_LAST
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index 63ae9e1..f971a0d 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -55,6 +55,7 @@ static virClassPtr virDomainEventPMClass;
static virClassPtr virDomainQemuMonitorEventClass;
static virClassPtr virDomainEventTunableClass;
static virClassPtr virDomainEventAgentLifecycleClass;
+static virClassPtr virDomainEventChannelLifecycleClass;
static virClassPtr virDomainEventDeviceAddedClass;
static virClassPtr virDomainEventMigrationIterationClass;
static virClassPtr virDomainEventJobCompletedClass;
@@ -75,6 +76,7 @@ static void virDomainEventPMDispose(void *obj);
static void virDomainQemuMonitorEventDispose(void *obj);
static void virDomainEventTunableDispose(void *obj);
static void virDomainEventAgentLifecycleDispose(void *obj);
+static void virDomainEventChannelLifecycleDispose(void *obj);
static void virDomainEventDeviceAddedDispose(void *obj);
static void virDomainEventMigrationIterationDispose(void *obj);
static void virDomainEventJobCompletedDispose(void *obj);
@@ -241,6 +243,16 @@ struct _virDomainEventAgentLifecycle {
typedef struct _virDomainEventAgentLifecycle virDomainEventAgentLifecycle;
typedef virDomainEventAgentLifecycle *virDomainEventAgentLifecyclePtr;
+struct _virDomainEventChannelLifecycle {
+ virDomainEvent parent;
+
+ char *channelName;
+ int state;
+ int reason;
+};
+typedef struct _virDomainEventChannelLifecycle virDomainEventChannelLifecycle;
+typedef virDomainEventChannelLifecycle *virDomainEventChannelLifecyclePtr;
+
struct _virDomainEventMigrationIteration {
virDomainEvent parent;
@@ -367,6 +379,12 @@ virDomainEventsOnceInit(void)
sizeof(virDomainEventAgentLifecycle),
virDomainEventAgentLifecycleDispose)))
return -1;
+ if (!(virDomainEventChannelLifecycleClass =
+ virClassNew(virDomainEventClass,
+ "virDomainEventChannelLifecycle",
+ sizeof(virDomainEventChannelLifecycle),
+ virDomainEventChannelLifecycleDispose)))
+ return -1;
if (!(virDomainEventMigrationIterationClass =
virClassNew(virDomainEventClass,
"virDomainEventMigrationIteration",
@@ -557,6 +575,15 @@ virDomainEventAgentLifecycleDispose(void *obj)
};
static void
+virDomainEventChannelLifecycleDispose(void *obj)
+{
+ virDomainEventChannelLifecyclePtr event = obj;
+ VIR_DEBUG("obj=%p", event);
+
+ VIR_FREE(event->channelName);
+};
+
+static void
virDomainEventMigrationIterationDispose(void *obj)
{
virDomainEventMigrationIterationPtr event = obj;
@@ -1460,6 +1487,56 @@ virDomainEventAgentLifecycleNewFromDom(virDomainPtr dom,
}
static virObjectEventPtr
+virDomainEventChannelLifecycleNew(int id,
+ const char *name,
+ const unsigned char *uuid,
+ const char *channelName,
+ int state,
+ int reason)
+{
+ virDomainEventChannelLifecyclePtr ev;
+
+ if (virDomainEventsInitialize() < 0)
+ return NULL;
+
+ if (!(ev = virDomainEventNew(virDomainEventChannelLifecycleClass,
+ VIR_DOMAIN_EVENT_ID_CHANNEL_LIFECYCLE,
+ id, name, uuid)))
+ return NULL;
+
+ if (VIR_STRDUP(ev->channelName, channelName) < 0) {
+ virObjectUnref(ev);
+ return NULL;
+ }
+
+ ev->state = state;
+ ev->reason = reason;
+
+ return (virObjectEventPtr)ev;
+}
+
+virObjectEventPtr
+virDomainEventChannelLifecycleNewFromObj(virDomainObjPtr obj,
+ const char *channelName,
+ int state,
+ int reason)
+{
+ return virDomainEventChannelLifecycleNew(obj->def->id, obj->def->name,
+ obj->def->uuid, channelName, state, reason);
+}
+
+virObjectEventPtr
+virDomainEventChannelLifecycleNewFromDom(virDomainPtr dom,
+ const char *channelName,
+ int state,
+ int reason)
+{
+ return virDomainEventChannelLifecycleNew(dom->id, dom->name, dom->uuid,
+ channelName, state, reason);
+}
+
+
+static virObjectEventPtr
virDomainEventMigrationIterationNew(int id,
const char *name,
const unsigned char *uuid,
@@ -1812,6 +1889,18 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
goto cleanup;
}
+ case VIR_DOMAIN_EVENT_ID_CHANNEL_LIFECYCLE:
+ {
+ virDomainEventChannelLifecyclePtr channelLifecycleEvent;
+ channelLifecycleEvent = (virDomainEventChannelLifecyclePtr)event;
+ ((virConnectDomainEventChannelLifecycleCallback)cb)(conn, dom,
+ channelLifecycleEvent->channelName,
+ channelLifecycleEvent->state,
+ channelLifecycleEvent->reason,
+ cbopaque);
+ goto cleanup;
+ }
+
case VIR_DOMAIN_EVENT_ID_DEVICE_ADDED:
{
virDomainEventDeviceAddedPtr deviceAddedEvent;
diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
index 54fa879..3a689b3 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -217,6 +217,18 @@ virDomainEventAgentLifecycleNewFromDom(virDomainPtr dom,
int reason);
virObjectEventPtr
+virDomainEventChannelLifecycleNewFromObj(virDomainObjPtr obj,
+ const char *channelName,
+ int state,
+ int reason);
+
+virObjectEventPtr
+virDomainEventChannelLifecycleNewFromDom(virDomainPtr dom,
+ const char *channelName,
+ int state,
+ int reason);
+
+virObjectEventPtr
virDomainEventMigrationIterationNewFromObj(virDomainObjPtr obj,
int iteration);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 74dd527..e259687 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -535,6 +535,8 @@ virDomainEventBlockJob2NewFromDom;
virDomainEventBlockJob2NewFromObj;
virDomainEventBlockJobNewFromDom;
virDomainEventBlockJobNewFromObj;
+virDomainEventChannelLifecycleNewFromDom;
+virDomainEventChannelLifecycleNewFromObj;
virDomainEventControlErrorNewFromDom;
virDomainEventControlErrorNewFromObj;
virDomainEventDeviceAddedNewFromDom;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 38c8414..b464412 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4407,6 +4407,7 @@ processSerialChangedEvent(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainChrDeviceState newstate;
virObjectEventPtr event = NULL;
+ virObjectEventPtr channelEvent = NULL;
virDomainDeviceDef dev;
qemuDomainObjPrivatePtr priv = vm->privateData;
int rc;
@@ -4482,6 +4483,10 @@ processSerialChangedEvent(virQEMUDriverPtr driver,
qemuDomainEventQueue(driver, event);
}
+ channelEvent = virDomainEventChannelLifecycleNewFromObj(vm, dev.data.chr->target.name, newstate,
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_CHANNEL);
+ qemuDomainEventQueue(driver, channelEvent);
+
endjob:
qemuDomainObjEndJob(driver, vm);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1b67aee..31b5028 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1931,6 +1931,7 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
int agentReason = VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL;
qemuMonitorChardevInfoPtr entry;
virObjectEventPtr event = NULL;
+ virObjectEventPtr channelEvent = NULL;
char id[32];
if (booted)
@@ -1958,6 +1959,11 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
agentReason)))
qemuDomainEventQueue(driver, event);
+
+ channelEvent =
+ virDomainEventChannelLifecycleNewFromObj(vm, chr->target.name, entry->state, agentReason);
+ qemuDomainEventQueue(driver, channelEvent);
+
chr->state = entry->state;
}
}
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index a3cd7cd..c778c42 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -345,6 +345,11 @@ remoteDomainBuildEventCallbackAgentLifecycle(virNetClientProgramPtr prog,
void *evdata, void *opaque);
static void
+remoteDomainBuildEventCallbackChannelLifecycle(virNetClientProgramPtr prog,
+ virNetClientPtr client,
+ void *evdata, void *opaque);
+
+static void
remoteDomainBuildEventCallbackMigrationIteration(virNetClientProgramPtr prog,
virNetClientPtr client,
void *evdata, void *opaque);
@@ -538,6 +543,10 @@ static virNetClientProgramEvent remoteEvents[] = {
remoteDomainBuildEventCallbackAgentLifecycle,
sizeof(remote_domain_event_callback_agent_lifecycle_msg),
(xdrproc_t)xdr_remote_domain_event_callback_agent_lifecycle_msg },
+ { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE,
+ remoteDomainBuildEventCallbackChannelLifecycle,
+ sizeof(remote_domain_event_callback_channel_lifecycle_msg),
+ (xdrproc_t)xdr_remote_domain_event_callback_channel_lifecycle_msg },
{ REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED,
remoteDomainBuildEventCallbackDeviceAdded,
sizeof(remote_domain_event_callback_device_added_msg),
@@ -5152,6 +5161,29 @@ remoteDomainBuildEventCallbackAgentLifecycle(virNetClientProgramPtr prog ATTRIBU
static void
+remoteDomainBuildEventCallbackChannelLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ remote_domain_event_callback_channel_lifecycle_msg *msg = evdata;
+ struct private_data *priv = conn->privateData;
+ virDomainPtr dom;
+ virObjectEventPtr event = NULL;
+
+ if (!(dom = get_nonnull_domain(conn, msg->dom)))
+ return;
+
+ event = virDomainEventChannelLifecycleNewFromDom(dom, msg->channelName, msg->state,
+ msg->reason);
+
+ virObjectUnref(dom);
+
+ remoteEventQueue(priv, event, msg->callbackID);
+}
+
+
+static void
remoteDomainBuildEventCallbackMigrationIteration(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
virNetClientPtr client ATTRIBUTE_UNUSED,
void *evdata,
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index e8382dc..e5227c4 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3242,6 +3242,15 @@ struct remote_domain_event_callback_agent_lifecycle_msg {
int reason;
};
+struct remote_domain_event_callback_channel_lifecycle_msg {
+ int callbackID;
+ remote_nonnull_domain dom;
+
+ char *channelName;
+ int state;
+ int reason;
+};
+
struct remote_connect_get_all_domain_stats_ret {
remote_domain_stats_record retStats<REMOTE_DOMAIN_LIST_MAX>;
};
@@ -5934,5 +5943,11 @@ enum remote_procedure {
* @generate: both
* @acl: none
*/
- REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377
+ REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377,
+
+ /**
+ * @generate: both
+ * @acl: none
+ */
+ REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE = 378
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index b71accc..7921016 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2689,6 +2689,13 @@ struct remote_domain_event_callback_agent_lifecycle_msg {
int state;
int reason;
};
+struct remote_domain_event_callback_channel_lifecycle_msg {
+ int callbackID;
+ remote_nonnull_domain dom;
+ remote_string channelName;
+ int state;
+ int reason;
+};
struct remote_connect_get_all_domain_stats_ret {
struct {
u_int retStats_len;
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 184f64d..e085358 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -12637,6 +12637,20 @@ VIR_ENUM_IMPL(virshEventAgentLifecycleReason,
N_("domain started"),
N_("channel event"))
+VIR_ENUM_DECL(virshEventChannelLifecycleState)
+VIR_ENUM_IMPL(virshEventChannelLifecycleState,
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_STATE_LAST,
+ N_("unknown"),
+ N_("connected"),
+ N_("disconnected"))
+
+VIR_ENUM_DECL(virshEventChannelLifecycleReason)
+VIR_ENUM_IMPL(virshEventChannelLifecycleReason,
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_LAST,
+ N_("unknown"),
+ N_("domain started"),
+ N_("channel event"))
+
#define UNKNOWNSTR(str) (str ? str : N_("unsupported value"))
static void
virshEventAgentLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -12656,6 +12670,25 @@ virshEventAgentLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
}
static void
+virshEventChannelLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *channelName,
+ int state,
+ int reason,
+ void *opaque)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferAsprintf(&buf, _("event 'channel-lifecycle' for domain %s: name: '%s', "
+ "state: '%s' reason: '%s'\n"),
+ virDomainGetName(dom),
+ channelName,
+ UNKNOWNSTR(virshEventChannelLifecycleStateTypeToString(state)),
+ UNKNOWNSTR(virshEventChannelLifecycleReasonTypeToString(reason)));
+ virshEventPrint(opaque, &buf);
+}
+
+static void
virshEventMigrationIterationPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
int iteration,
@@ -12755,6 +12788,8 @@ static vshEventCallback vshEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(virshEventJobCompletedPrint), },
{ "device-removal-failed",
VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceRemovalFailedPrint), },
+ { "channel-lifecycle",
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventChannelLifecyclePrint), },
};
verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
--
2.7.4 (Apple Git-66)
8 years, 1 month
Re: [libvirt] [PATCH v4 7/8] qmp: Support abstract classes on device-list-properties
by Eduardo Habkost
(CCing libvirt people, as I forgot to CC them)
On Mon, Oct 31, 2016 at 03:07:23PM +0100, Igor Mammedov wrote:
> On Fri, 28 Oct 2016 23:48:06 -0200
> Eduardo Habkost <ehabkost(a)redhat.com> wrote:
>
> > When an abstract class is used on device-list-properties, we can
> > simply return the class properties registered for the class.
> >
> > This will be useful if management software needs to query for
> > supported options that apply to all devices of a given type (e.g.
> > options supported by all CPU models, options supported by all PCI
> > devices).
> Patch looks fine to me but I'm not qmp interface guru
> so I'd leave review up to maintainers.
>
> One question though,
> How would management software discover typename of abstract class?
It depends on the use case. On some cases, management may already
have bus-specific logic that will know what's the base type it
needs to query (e.g. it may query "pci-device" to find out if all
PCI devices support a given option). On other cases, it may be
discovered using other commands.
For the CPU case, I will propose adding the base QOM CPU typename
in the query-target command.
>
> Perhaps this patch should be part of some other series.
This is a valid point. In this case, it depends on the approach
we want to take: do we want to provide a flexible interface for
management, let them find ways to make it useful and give us
feedback on what is lacking; or do we want to provide the new
interface only after we have specified the complete solution for
the problem?
I don't know the answer. I will let the qdev/QOM/QMP maintainers
answer that.
>
> > Signed-off-by: Eduardo Habkost <ehabkost(a)redhat.com>
> > ---
> > Changes series v1 -> v2:
> > * (none)
> >
> > Changes series v2 -> v3:
> > * Reworded commit message
> >
> > Changes series v3 -> v4:
> > * (none)
> > ---
> > qmp.c | 21 +++++++++------------
> > 1 file changed, 9 insertions(+), 12 deletions(-)
> >
> > diff --git a/qmp.c b/qmp.c
> > index a06cb7b..1e7e60d 100644
> > --- a/qmp.c
> > +++ b/qmp.c
> > @@ -518,7 +518,7 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
> > Error **errp)
> > {
> > ObjectClass *klass;
> > - Object *obj;
> > + Object *obj = NULL;
> > ObjectProperty *prop;
> > ObjectPropertyIterator iter;
> > DevicePropertyInfoList *prop_list = NULL;
> > @@ -537,19 +537,16 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
> > }
> >
> > if (object_class_is_abstract(klass)) {
> > - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "name",
> > - "non-abstract device type");
> > - return NULL;
> > - }
> > -
> > - if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
> > - error_setg(errp, "Can't list properties of device '%s'", typename);
> > - return NULL;
> > + object_class_property_iter_init(&iter, klass);
> > + } else {
> > + if (DEVICE_CLASS(klass)->cannot_destroy_with_object_finalize_yet) {
> > + error_setg(errp, "Can't list properties of device '%s'", typename);
> > + return NULL;
> > + }
> > + obj = object_new(typename);
> > + object_property_iter_init(&iter, obj);
> > }
> >
> > - obj = object_new(typename);
> > -
> > - object_property_iter_init(&iter, obj);
> > while ((prop = object_property_iter_next(&iter))) {
> > DevicePropertyInfo *info;
> > DevicePropertyInfoList *entry;
>
--
Eduardo
8 years, 1 month
[libvirt] [PATCH v3 0/2] List only online cpus for vcpupin/emulatorpin when vcpu placement static
by Nitesh Konkar
Currently when the vcpu placement is static and
cpuset is not specified, CPU Affinity shows 0..
CPUMAX. This patchset will result in display of
only online CPU's under CPU Affinity on linux.
Nitesh Konkar (2):
conf: List only online cpus for virsh vcpupin
conf: List only online cpus for virsh emulatorpin
src/conf/domain_conf.c | 10 ++++++++++
src/qemu/qemu_driver.c | 9 +++++++++
2 files changed, 19 insertions(+)
--
2.1.0
8 years, 1 month
[libvirt] [PATCH v3 python 0/2] fix crash in libvirt_virDomainPin*
by Konstantin Neumoin
this small patch set:
* move common logic of all libvirt_virDomainPin* functions to new helper
in util module.
* fix overrun buffer when converting cpumap.
Changes since v2:
- fix comments for new helper function
- remove extra variables and labels
- fix commit message/subject
- rename new helper function
Changes since v1:
- add new helper in util module.
Konstantin Neumoin (2):
move cpumap conversion code to a common helper
don't overrun buffer when converting cpumap
libvirt-override.c | 131 +++++------------------------------------------------
libvirt-utils.c | 62 +++++++++++++++++++++++++
libvirt-utils.h | 5 ++
3 files changed, 78 insertions(+), 120 deletions(-)
--
2.5.5
8 years, 1 month