[libvirt] [PATCHv2] 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 | 44 ++++++++++++++++++
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, 347 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..9a5c664 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3965,6 +3965,49 @@ 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 =
+ VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_DOMAIN_STARTED, /* state changed due to domain start */
+ VIR_CONNECT_DOMAIN_EVENT_CHANNEL_LIFECYCLE_REASON_CHANNEL =
+ VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_CHANNEL, /* 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 hypervisor must support serial notification, and this is
+ * currently limited to modern versions of qemu.
+ *
+ * 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 +4049,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..eb783cb 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);
@@ -574,6 +579,10 @@ static virNetClientProgramEvent remoteEvents[] = {
remoteNodeDeviceBuildEventUpdate,
sizeof(remote_node_device_event_update_msg),
(xdrproc_t)xdr_remote_node_device_event_update_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 },
};
static void
@@ -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)
7 years, 8 months
[libvirt] question about connection between vms in two physical hosts
by 无敌浪子
Hi there,
I have some vms in two different physical hosts, the hosts are connected directly instead of a switcher, I'd like to make all these vms connected. the condition right now is that vm network type is nat, vm behind nat cannot get the new connection inbound, I suppose if I can make the inbound connection acceptable or if there is any other solution ? Thank you
best wishes
bill
7 years, 8 months
[libvirt] OSX Homebrew support note ;)
by Justin Clift
Hi all,
Compiling Libvirt directly from latest git master head is now supported
on
OSX Homebrew. It's as simple as:
$ brew install --HEAD libvirt
...
$ virsh -v
3.0.0
This should make development of Libvirt and related virtualisation
things
much easier on OSX. :)
The credit for this goes to Roman Bogorodskiy and Homebrew developer
"ilovezfs" (CC-d), for adding a functional rpcgen to Homebrew so we can
generate the needed RPC bindings during the build (previously missing).
Thanks heaps! :)
Regards and best wishes,
Justin Clift
7 years, 8 months
[libvirt] [PATCHv4 0/3] Add support for file memorybacking
by Jaroslav Safka
Hi,
we would like to introduce 3 new elements source,access and allocation in memoryBacking element.
For now it was made for numa topology.
<memoryBacking>
<source type="file|anonymous"/>
<access mode="shared|private"/>
<allocation mode="immediate|ondemand"/>
</memoryBacking>
If allocation is immediate then -mem-prealloc should be added to the qemu commanline.
If source is file then
-object memory-backend-file,id=mem,size=1024M,mem-path=*lib dir path* -numa node,memdev=mem Will be added to the qemu commandline
If access is shared then the "share=on" parameter will be added to the memory-backend-file e.g.
-object memory-backend-file,id=mem,size=1024M,mem-path=/var/lib/libvirt/qemu,share=on
The access mode can be overriden by specifying token memAccess in numa cell.
The test cpu-numa-memshared was removed, because behaviour was changed and is not needed anymore
Jaroslav Safka (3):
qemu,conf: Rename virNumaMemAccess to virDomainMemoryAccess
conf: Add new xml elements for file memorybacking support
qemu: Add args generation for file memory backing
docs/formatdomain.html.in | 9 ++
docs/schemas/domaincommon.rng | 30 +++++
src/conf/domain_conf.c | 133 ++++++++++++++++-----
src/conf/domain_conf.h | 22 ++++
src/conf/numa_conf.c | 15 +--
src/conf/numa_conf.h | 14 +--
src/qemu/qemu_command.c | 123 ++++++++++++-------
src/qemu/qemu_process.c | 2 +-
.../qemuxml2argv-fd-memory-no-numa-topology.args | 21 ++++
.../qemuxml2argv-fd-memory-no-numa-topology.xml | 27 +++++
.../qemuxml2argv-fd-memory-numa-topology.args | 24 ++++
.../qemuxml2argv-fd-memory-numa-topology.xml | 30 +++++
.../qemuxml2argv-fd-memory-numa-topology2.args | 26 ++++
.../qemuxml2argv-fd-memory-numa-topology2.xml | 31 +++++
.../qemuxml2argv-fd-memory-numa-topology3.args | 30 +++++
.../qemuxml2argv-fd-memory-numa-topology3.xml | 32 +++++
.../qemuxml2argv-memorybacking-set.xml | 24 ++++
.../qemuxml2argv-memorybacking-unset.xml | 24 ++++
tests/qemuxml2argvtest.c | 12 +-
.../qemuxml2xmlout-memorybacking-set.xml | 32 +++++
.../qemuxml2xmlout-memorybacking-unset.xml | 32 +++++
tests/qemuxml2xmltest.c | 4 +-
22 files changed, 605 insertions(+), 92 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology2.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology2.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology3.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology3.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
--
2.7.4
--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263
This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.
7 years, 9 months
[libvirt] [PATCH] vz: don't show bootorder for containers
by Nikolay Shirokovskiy
Because this is invalid xml for containers. This patch almost
reverts 7eda8369, but still skips converting vz sdk bootorder
for containers to libvirt bootorder because we use boot order
in containers for quite different purpurse.
---
I know I reviewed this code just recently. It is just got out
of my sight.
src/vz/vz_sdk.c | 23 ++---------------------
1 file changed, 2 insertions(+), 21 deletions(-)
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
index ced58e5..43a6340 100644
--- a/src/vz/vz_sdk.c
+++ b/src/vz/vz_sdk.c
@@ -1695,21 +1695,6 @@ prlsdkBootOrderCheck(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE sdkType, int sdkIndex,
return ret;
}
-static void
-prlsdkConvertBootOrderCt(virDomainDefPtr def)
-{
- size_t i;
- for (i = 0; i < def->nfss; i++) {
-
- if (STREQ(def->fss[i]->dst, "/")) {
- def->os.nBootDevs = 0;
- return;
- }
- }
- def->os.nBootDevs = 1;
- def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
-}
-
static int
prlsdkConvertBootOrderVm(PRL_HANDLE sdkdom, virDomainDefPtr def)
{
@@ -1870,12 +1855,8 @@ prlsdkLoadDomain(vzDriverPtr driver,
goto error;
/* depends on prlsdkAddDomainHardware */
- if (IS_CT(def)) {
- prlsdkConvertBootOrderCt(def);
- } else {
- if (prlsdkConvertBootOrderVm(sdkdom, def) < 0)
- goto error;
- }
+ if (!IS_CT(def) && prlsdkConvertBootOrderVm(sdkdom, def) < 0)
+ goto error;
pret = PrlVmCfg_GetEnvId(sdkdom, &envId);
prlsdkCheckRetGoto(pret, error);
--
1.8.3.1
7 years, 9 months
[libvirt] [PATCH 0/5] implement .connectGetAllDomainStats
by Nikolay Shirokovskiy
Nikolay Shirokovskiy (5):
vz: provide block stats for all domain stats
vz: add net group to all domain stats
vz: add vcpu group to all domain stats
vz: add balloon group to all domain stats
vz: add state group to all domain stats
src/vz/vz_driver.c | 366 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/vz/vz_sdk.c | 8 ++
2 files changed, 374 insertions(+)
--
1.8.3.1
7 years, 9 months
[libvirt] [PATCH v3] qemu: set default vhost-user ifname
by Michal Privoznik
Based on work of Mehdi Abaakouk <sileht(a)sileht.net>.
When parsing vhost-user interface XML and no ifname is found we
can try to fill it in in post parse callback. The way this works
is we try to make up interface name from given socket path and
then ask openvswitch wether it knows the interface.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
diff to v2:
- All the review points from v2 worked in
src/libvirt_private.syms | 1 +
src/qemu/qemu_domain.c | 21 +++++---
src/util/virnetdevopenvswitch.c | 58 ++++++++++++++++++++++
src/util/virnetdevopenvswitch.h | 4 ++
tests/Makefile.am | 7 +++
tests/qemuxml2argvmock.c | 8 +++
tests/qemuxml2xmlmock.c | 33 ++++++++++++
.../qemuxml2xmlout-net-vhostuser.xml | 2 +
tests/qemuxml2xmltest.c | 2 +-
9 files changed, 129 insertions(+), 7 deletions(-)
create mode 100644 tests/qemuxml2xmlmock.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2d23e462d..9e4e8f83f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2057,6 +2057,7 @@ virNetDevMidonetUnbindPort;
# util/virnetdevopenvswitch.h
virNetDevOpenvswitchAddPort;
virNetDevOpenvswitchGetMigrateData;
+virNetDevOpenvswitchGetVhostuserIfname;
virNetDevOpenvswitchInterfaceStats;
virNetDevOpenvswitchRemovePort;
virNetDevOpenvswitchSetMigrateData;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index acfa69589..eed5745b6 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -41,6 +41,7 @@
#include "domain_addr.h"
#include "domain_event.h"
#include "virtime.h"
+#include "virnetdevopenvswitch.h"
#include "virstoragefile.h"
#include "virstring.h"
#include "virthreadjob.h"
@@ -3028,12 +3029,20 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
def->emulator);
}
- if (dev->type == VIR_DOMAIN_DEVICE_NET &&
- dev->data.net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
- !dev->data.net->model) {
- if (VIR_STRDUP(dev->data.net->model,
- qemuDomainDefaultNetModel(def, qemuCaps)) < 0)
- goto cleanup;
+ if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+ if (dev->data.net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+ !dev->data.net->model) {
+ if (VIR_STRDUP(dev->data.net->model,
+ qemuDomainDefaultNetModel(def, qemuCaps)) < 0)
+ goto cleanup;
+ }
+ if (dev->data.net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
+ !dev->data.net->ifname) {
+ if (virNetDevOpenvswitchGetVhostuserIfname(
+ dev->data.net->data.vhostuser->data.nix.path,
+ &dev->data.net->ifname) < 0)
+ goto cleanup;
+ }
}
/* set default disk types and drivers */
diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
index f003b3b13..d93653317 100644
--- a/src/util/virnetdevopenvswitch.c
+++ b/src/util/virnetdevopenvswitch.c
@@ -377,3 +377,61 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
virCommandFree(cmd);
return ret;
}
+
+/**
+ * virNetDevOpenvswitchVhostuserGetIfname:
+ * @path: the path of the unix socket
+ * @ifname: the retrieved name of the interface
+ *
+ * Retreives the ovs ifname from vhostuser unix socket path.
+ *
+ * Returns: 1 if interface is an openvswitch interface,
+ * 0 if it is not, but no other error occurred,
+ * -1 otherwise.
+ */
+int
+virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+ char **ifname)
+{
+ virCommandPtr cmd = NULL;
+ char *tmpIfname = NULL;
+ char **tokens = NULL;
+ size_t ntokens = 0;
+ int status;
+ int ret = -1;
+
+ /* Openvswitch vhostuser path are hardcoded to
+ * /<runstatedir>/openvswitch/<ifname>
+ * for example: /var/run/openvswitch/dpdkvhostuser0
+ *
+ * so we pick the filename and check it's a openvswitch interface
+ */
+ if ((tokens = virStringSplitCount(path, "/", 0, &ntokens))) {
+ if (VIR_STRDUP(tmpIfname, tokens[ntokens - 1]) < 0)
+ goto cleanup;
+ }
+
+ if (!tmpIfname) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ cmd = virCommandNewArgList(OVSVSCTL, "--timeout=5", "get", "Interface",
+ tmpIfname, "name", NULL);
+ if (virCommandRun(cmd, &status) < 0 ||
+ status) {
+ /* it's not a openvswitch vhostuser interface. */
+ ret = 0;
+ goto cleanup;
+ }
+
+ *ifname = tmpIfname;
+ tmpIfname = NULL;
+ ret = 1;
+
+ cleanup:
+ virStringListFreeCount(tokens, ntokens);
+ virCommandFree(cmd);
+ VIR_FREE(tmpIfname);
+ return ret;
+}
diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h
index 0f9e1dfa6..8f5faf14e 100644
--- a/src/util/virnetdevopenvswitch.h
+++ b/src/util/virnetdevopenvswitch.h
@@ -52,4 +52,8 @@ int virNetDevOpenvswitchInterfaceStats(const char *ifname,
virDomainInterfaceStatsPtr stats)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+ char **ifname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
#endif /* __VIR_NETDEV_OPENVSWITCH_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ecd04e895..c8584fea6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -414,6 +414,7 @@ if WITH_QEMU
test_libraries += libqemumonitortestutils.la \
libqemutestdriver.la \
qemuxml2argvmock.la \
+ qemuxml2xmlmock.la \
qemucaps2xmlmock.la \
qemucapsprobemock.la \
$(NULL)
@@ -571,6 +572,12 @@ qemuxml2argvmock_la_CFLAGS = $(AM_CFLAGS)
qemuxml2argvmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
qemuxml2argvmock_la_LIBADD = $(MOCKLIBS_LIBS)
+qemuxml2xmlmock_la_SOURCES = \
+ qemuxml2xmlmock.c
+qemuxml2xmlmock_la_CFLAGS = $(AM_CFLAGS)
+qemuxml2xmlmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS)
+qemuxml2xmlmock_la_LIBADD = $(MOCKLIBS_LIBS)
+
qemuxml2xmltest_SOURCES = \
qemuxml2xmltest.c testutilsqemu.c testutilsqemu.h \
testutils.c testutils.h
diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c
index c501b59ac..177b24e0a 100644
--- a/tests/qemuxml2argvmock.c
+++ b/tests/qemuxml2argvmock.c
@@ -28,6 +28,7 @@
#include "virnetdev.h"
#include "virnetdevip.h"
#include "virnetdevtap.h"
+#include "virnetdevopenvswitch.h"
#include "virnuma.h"
#include "virrandom.h"
#include "virscsi.h"
@@ -180,3 +181,10 @@ virCryptoGenerateRandom(size_t nbytes)
return buf;
}
+
+int
+virNetDevOpenvswitchGetVhostuserIfname(const char *path ATTRIBUTE_UNUSED,
+ char **ifname)
+{
+ return VIR_STRDUP(*ifname, "vhost-user0");
+}
diff --git a/tests/qemuxml2xmlmock.c b/tests/qemuxml2xmlmock.c
new file mode 100644
index 000000000..0d3e6f2bd
--- /dev/null
+++ b/tests/qemuxml2xmlmock.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Red Hat, 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Michal Privoznik <mprivozn(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include "virnetdevopenvswitch.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+int
+virNetDevOpenvswitchGetVhostuserIfname(const char *path ATTRIBUTE_UNUSED,
+ char **ifname)
+{
+ return VIR_STRDUP(*ifname, "vhost-user0");
+}
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml
index ac1d7e110..2bdcac358 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml
@@ -30,12 +30,14 @@
<interface type='vhostuser'>
<mac address='52:54:00:ee:96:6b'/>
<source type='unix' path='/tmp/vhost0.sock' mode='server'/>
+ <target dev='vhost-user0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<interface type='vhostuser'>
<mac address='52:54:00:ee:96:6c'/>
<source type='unix' path='/tmp/vhost1.sock' mode='client'/>
+ <target dev='vhost-user0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</interface>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index ddd17cb1e..30931f581 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1031,7 +1031,7 @@ mymain(void)
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
-VIRT_TEST_MAIN(mymain)
+VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/qemuxml2xmlmock.so")
#else
--
2.11.0
7 years, 9 months
[libvirt] [PATCH] storage_backend_rbd: always call rados_conf_read_file when connect a rbd pool
by Chen Hanxiao
From: Chen Hanxiao <chenhanxiao(a)gmail.com>
This patch fix a dead lock when try to read a rbd image
When trying to connect a rbd server
(ceph-0.94.7-1.el7.centos.x86_64),
rbd_list/rbd_open enter a dead lock state.
Backtrace:
Thread 30 (Thread 0x7fdb342d0700 (LWP 12105)):
#0 0x00007fdb40b16705 in pthread_cond_wait@(a)GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fdb294273f1 in librados::IoCtxImpl::operate_read(object_t const&, ObjectOperation*, ceph::buffer::list*, int) () from /lib64/librados.so.2
#2 0x00007fdb29429fcc in librados::IoCtxImpl::read(object_t const&, ceph::buffer::list&, unsigned long, unsigned long) () from /lib64/librados.so.2
#3 0x00007fdb293e850c in librados::IoCtx::read(std::string const&, ceph::buffer::list&, unsigned long, unsigned long) () from /lib64/librados.so.2
#4 0x00007fdb2b9dd15e in librbd::list(librados::IoCtx&, std::vector<std::string, std::allocator<std::string> >&) () from /lib64/librbd.so.1
#5 0x00007fdb2b98c089 in rbd_list () from /lib64/librbd.so.1
#6 0x00007fdb2e1a8052 in virStorageBackendRBDRefreshPool (conn=<optimized out>, pool=0x7fdafc002d50) at storage/storage_backend_rbd.c:366
#7 0x00007fdb2e193833 in storagePoolCreate (obj=0x7fdb1c1fd5a0, flags=<optimized out>) at storage/storage_driver.c:876
#8 0x00007fdb43790ea1 in virStoragePoolCreate (pool=pool@entry=0x7fdb1c1fd5a0, flags=0) at libvirt-storage.c:695
#9 0x00007fdb443becdf in remoteDispatchStoragePoolCreate (server=0x7fdb45fb2ab0, msg=0x7fdb45fb3db0, args=0x7fdb1c0037d0, rerr=0x7fdb342cfc30, client=<optimized out>) at remote_dispatch.h:14383
#10 remoteDispatchStoragePoolCreateHelper (server=0x7fdb45fb2ab0, client=<optimized out>, msg=0x7fdb45fb3db0, rerr=0x7fdb342cfc30, args=0x7fdb1c0037d0, ret=0x7fdb1c1b3260) at remote_dispatch.h:14359
#11 0x00007fdb437d9c42 in virNetServerProgramDispatchCall (msg=0x7fdb45fb3db0, client=0x7fdb45fd1a80, server=0x7fdb45fb2ab0, prog=0x7fdb45fcd670) at rpc/virnetserverprogram.c:437
#12 virNetServerProgramDispatch (prog=0x7fdb45fcd670, server=server@entry=0x7fdb45fb2ab0, client=0x7fdb45fd1a80, msg=0x7fdb45fb3db0) at rpc/virnetserverprogram.c:307
#13 0x00007fdb437d4ebd in virNetServerProcessMsg (msg=<optimized out>, prog=<optimized out>, client=<optimized out>, srv=0x7fdb45fb2ab0) at rpc/virnetserver.c:135
#14 virNetServerHandleJob (jobOpaque=<optimized out>, opaque=0x7fdb45fb2ab0) at rpc/virnetserver.c:156
#15 0x00007fdb436cfb35 in virThreadPoolWorker (opaque=opaque@entry=0x7fdb45fa7650) at util/virthreadpool.c:145
#16 0x00007fdb436cf058 in virThreadHelper (data=<optimized out>) at util/virthread.c:206
#17 0x00007fdb40b12df5 in start_thread () from /lib64/libpthread.so.0
#18 0x00007fdb408401ad in clone () from /lib64/libc.so.6
366 len = rbd_list(ptr.ioctx, names, &max_size);
(gdb) n
[New Thread 0x7fdb20758700 (LWP 22458)]
[New Thread 0x7fdb20556700 (LWP 22459)]
[Thread 0x7fdb20758700 (LWP 22458) exited]
[New Thread 0x7fdb20455700 (LWP 22460)]
[Thread 0x7fdb20556700 (LWP 22459) exited]
[New Thread 0x7fdb20556700 (LWP 22461)]
infinite loop...
Signed-off-by: Chen Hanxiao <chenhanxiao(a)gmail.com>
---
src/storage/storage_backend_rbd.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index b1c51ab..233737b 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -95,6 +95,9 @@ virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
goto cleanup;
}
+ /* try default location, but ignore failure */
+ rados_conf_read_file(ptr->cluster, NULL);
+
if (!conn) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("'ceph' authentication not supported "
@@ -124,6 +127,10 @@ virStorageBackendRBDOpenRADOSConn(virStorageBackendRBDStatePtr ptr,
_("failed to create the RADOS cluster"));
goto cleanup;
}
+
+ /* try default location, but ignore failure */
+ rados_conf_read_file(ptr->cluster, NULL);
+
if (virStorageBackendRBDRADOSConfSet(ptr->cluster,
"auth_supported", "none") < 0)
goto cleanup;
--
2.7.4
7 years, 9 months
[libvirt] [PATCH v5 0/3] gluster: cache glfs connection object per volume
by Prasanna Kumar Kalever
v5: Address review comments from Peter on v4
Dropping Patch 3 from v3
Patch 1: fix transport type in all drivers, possible switch case converts
Patch 2: use virObject with src->drv to avoid 'initFlag' for
remembering 'virStorageFileInit' status
Patch 3:
* change virStorageBackendGlusterCacheQuery to *Lookup
* change virStorageBackendGlusterCacheRefresh to *Release
* Avoid the global Flags
* Thread safe measure by using virCond*
Thanks Peter!
v4: Address review comments from Peter on v3
Patch 1: changes to fix test failures
(qemuargv2xmltest, qemuxml2argvtest, qemuxml2xmltest and virstoragetest)
Patch 2: fix hung in qemuxml2argvtest
Patch 3 v3: Split this Patch to 2 parts as below
Patch 3 v4: don't free metadata used for storage driver access
Patch 4:
* update variable naming as per standards
* virStorageBackendGlusterPreopened* -> virStorageBackendGlusterCache*
Thanks Peter!
v3: Address comments by Daniel and Peter on v2
* Split the patch to 3 parts
Patch 1: change the virStorageNetHostDef type
Patch 2: optimize calls to virStorageFileInit and friends
Patch 3: add the caching for glfs
* Thanks to Daniel, this version make all the methods as thread safe
* Thanks to Peter for pointing use of virObjectLockable, this had simplified
rest of the parts a lot.
v2: Address review comments from Peter on v1
* Rebased on latest master
* Changes to commit msg
* Introduce storage API's for Register and Unregister of volume
* During qemu process Start/Stop and snapshot create
* Check Transport and Port type
* Atomic element add/del to list and ref counting
Pending: Treating IP and FQDN belong to same host
v1: Initial patch
Prasanna Kumar Kalever (3):
util: change the virStorageNetHostDef type
storage: optimize calls to virStorageFileInit and friends
gluster: cache glfs connection object per volume
src/conf/domain_conf.c | 60 +++--
src/libxl/libxl_conf.c | 10 +-
src/qemu/qemu_command.c | 97 ++++---
src/qemu/qemu_domain.c | 25 +-
src/qemu/qemu_domain.h | 8 +-
src/qemu/qemu_driver.c | 26 +-
src/qemu/qemu_parse_command.c | 50 ++--
src/qemu/qemu_process.c | 49 ++++
src/qemu/qemu_process.h | 4 +
src/storage/storage_backend.h | 1 +
src/storage/storage_backend_fs.c | 5 +
src/storage/storage_backend_gluster.c | 329 ++++++++++++++++++++---
src/storage/storage_driver.c | 40 ++-
src/storage/storage_driver.h | 2 +
src/util/virstoragefile.c | 93 ++++---
src/util/virstoragefile.h | 21 +-
src/xenconfig/xen_xl.c | 10 +-
tests/domainsnapshotxml2xmlin/disk_snapshot.xml | 2 +-
tests/domainsnapshotxml2xmlout/disk_snapshot.xml | 2 +-
tests/virstoragetest.c | 2 +-
20 files changed, 614 insertions(+), 222 deletions(-)
--
2.7.4
7 years, 9 months
[libvirt] Performance about x-data-plane
by Weiwei Jia
Hi,
With QEMU x-data-plane, I find the performance has not been improved
very much. Please see following two settings.
Setting 1: I/O thread in host OS (VMM) reads 4KB each time from disk
(8GB in total). Pin the I/O thread to pCPU 5 which will serve I/O
thread dedicatedly. I find the performance is around 250 MB/s.
Setting 2: I/O thread in guest OS (VMM) reads 4KB each time from
virtual disk (8GB in total). Pin the I/O thread to vCPU 5 and pin vCPU
5 thread to pCPU5 so that vCPU 5 handles this I/O thread dedicatedly
and pCPU5 serve vCPU5 dedicatedly. In order to keep vCPU5 not to be
idle, I also pin one cpu intensive thread (while (1) {i++}) on vCPU 5
so that the I/O thread on it can be served without delay. For this
setting, I find the performance for this I/O thread is around 190
MB/s.
NOTE: For setting 2, I also pin the QEMU dedicated IOthread
(x-data-plane) in host OS to pCPU to handle I/O requests from guest OS
dedicatedly.
I think for setting 2, the performance of I/O thread should be almost
the same as setting 1. I cannot understand why it is 60 MB/s lower
than setting 1. I am wondering whether there are something wrong with
my x-data-plane setting or virtio setting for VM. Would you please
give me some hints? Thank you.
Libvirt version: 2.4.0
QEMU version: 2.3.0
The libvirt xml configuration file is like following (I only start
one VM with following xml config).
<domain type='kvm' id='1'
xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name>vm</name>
<uuid>3290a8d0-9d9f-b2c4-dd46-5d0d8a730cd6</uuid>
<memory unit='KiB'>8290304</memory>
<currentMemory unit='KiB'>8290304</currentMemory>
<vcpu placement='static'>15</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='1'/>
<vcpupin vcpu='2' cpuset='2'/>
<vcpupin vcpu='3' cpuset='3'/>
<vcpupin vcpu='4' cpuset='4'/>
<vcpupin vcpu='5' cpuset='5'/>
<vcpupin vcpu='6' cpuset='6'/>
<vcpupin vcpu='7' cpuset='7'/>
<vcpupin vcpu='8' cpuset='8'/>
<vcpupin vcpu='9' cpuset='9'/>
<vcpupin vcpu='10' cpuset='10'/>
<vcpupin vcpu='11' cpuset='11'/>
<vcpupin vcpu='12' cpuset='12'/>
<vcpupin vcpu='13' cpuset='13'/>
<vcpupin vcpu='14' cpuset='14'/>
</cputune>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-2.2'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/kvm-spice</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw' cache='none' io='native'/>
<source file='/var/lib/libvirt/images/vm.img'/>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06'
function='0x0'/>
</disk>
<disk type='block' device='cdrom'>
<driver name='qemu' type='raw'/>
<target dev='hdc' bus='ide'/>
<readonly/>
<alias name='ide0-1-0'/>
<address type='drive' controller='0' bus='1' target='0' unit='0'/>
</disk>
<controller type='usb' index='0'>
<alias name='usb0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01'
function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<controller type='ide' index='0'>
<alias name='ide0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01'
function='0x1'/>
</controller>
<controller type='scsi' index='0'>
<alias name='scsi0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04'
function='0x0'/>
</controller>
<interface type='network'>
<mac address='52:54:00:8e:3d:06'/>
<source network='default'/>
<target dev='vnet0'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03'
function='0x0'/>
</interface>
<serial type='pty'>
<source path='/dev/pts/8'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/8'>
<source path='/dev/pts/8'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02'
function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05'
function='0x0'/>
</memballoon>
</devices>
<seclabel type='none'/>
<qemu:commandline>
<qemu:arg value='-set'/>
<qemu:arg value='device.virtio-disk0.scsi=off'/>
<qemu:arg value='-set'/>
<qemu:arg value='device.virtio-disk0.config-wce=off'/>
<qemu:arg value='-set'/>
<qemu:arg value='device.virtio-disk0.x-data-plane=on'/>
</qemu:commandline>
</domain>
Thank you,
Weiwei Jia
7 years, 9 months