Re: [libvirt] [Qemu-devel] [PATCH] qdev: Make "hotplugged" property read-only
by Eduardo Habkost
(CCing libvir-list and Laine)
On Tue, Jan 03, 2017 at 05:53:27PM +0100, Igor Mammedov wrote:
> On Tue, 3 Jan 2017 17:10:15 +0100
> Paolo Bonzini <pbonzini(a)redhat.com> wrote:
>
> >
> >
> > On 03/01/2017 15:22, Eduardo Habkost wrote:
> > >> I didn't know that. Is this documented somewhere?
> > >> Is it actually used by any existing software?
> > > not that I know of. But users should be fixed if they are not using it.
> > >
> > > I see. The problem is that the mechanism is undocumented,
> > > untested, and seems very likely to trigger bugs in device code.
> >
> > I agree. Why can't hotplugged be migrated?
> It's probably not migrated because of it's not runtime/guest modified
> state so we don't have to migrate it as it's know in advance.
>
> For now it should set manually on CLI (-device) with the rest of
> hotplugged device properties.
As this recommendation has the potential to trigger hidden bugs
(and known to trigger a bug in QEMU <= 2.8), I would like it to
be properly documented, and the documentation/recommendations
reviewed following the usual patch review process.
While we don't do that, setting "hotplugged=true" on the
command-line is an unused, undocumented, untested (and
unsupported?) feature.
--
Eduardo
7 years, 10 months
[libvirt] [PATCH v2 0/4] Virtio-crypto device support
by Longpeng(Mike)
As virtio-crypto has been supported in QEMU 2.8 and the frontend
driver has been merged in linux 4.10, so it's necessary to support
virtio-crypto in libvirt.
---
Changes since v1:
- split patch [Martin]
- rebase on master [Martin]
- add docs/tests/schema [Martin]
- fix typos [Gonglei]
---
Longpeng(Mike) (4):
docs: schema: Add basic documentation for the virtual crypto device
support
conf: Parse virtio-crypto in the domain XML
qemu: Implement support for 'builtin' backend for virtio-crypto
tests: Add testcase for virtio-crypto XML parsing
docs/formatdomain.html.in | 60 ++++++
docs/schemas/domaincommon.rng | 27 +++
src/conf/domain_conf.c | 213 ++++++++++++++++++++-
src/conf/domain_conf.h | 32 ++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_alias.c | 20 ++
src/qemu/qemu_alias.h | 3 +
src/qemu/qemu_capabilities.c | 4 +
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 132 +++++++++++++
src/qemu/qemu_command.h | 3 +
src/qemu/qemu_domain.c | 2 +
src/qemu/qemu_domain_address.c | 25 +++
src/qemu/qemu_driver.c | 6 +
src/qemu/qemu_hotplug.c | 1 +
tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml | 2 +
tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 2 +
.../qemuxml2argv-virtio-crypto-builtin.xml | 26 +++
.../qemuxml2argv-virtio-crypto.args | 22 +++
.../qemuxml2xmlout-virtio-crypto-builtin.xml | 31 +++
tests/qemuxml2xmltest.c | 2 +
21 files changed, 616 insertions(+), 1 deletion(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-virtio-crypto-builtin.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-virtio-crypto.args
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-virtio-crypto-builtin.xml
--
1.8.3.1
7 years, 10 months
[libvirt] [PATCH] node_device: Check return value for udev_new()
by Marc Hartmayer
The comment was actually wrong as
https://www.freedesktop.org/software/systemd/man/udev_new.html
mentions that on failure NULL is returned.
Signed-off-by: Marc Hartmayer <mhartmay(a)linux.vnet.ibm.com>
Reviewed-by: Bjoern Walk <bwalk(a)linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy(a)linux.vnet.ibm.com>
---
src/node_device/node_device_udev.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 4b81312..4b0a875 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1491,13 +1491,11 @@ static int nodeStateInitialize(bool privileged,
if (udevPCITranslateInit(privileged) < 0)
goto cleanup;
- /*
- * http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/libudev-udev...
- *
- * indicates no return value other than success, so we don't check
- * its return value.
- */
udev = udev_new();
+ if (!udev) {
+ virReportOOMError();
+ goto cleanup;
+ }
#if HAVE_UDEV_LOGGING
/* cast to get rid of missing-format-attribute warning */
udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
--
2.5.5
7 years, 10 months
[libvirt] [PATCH 00/15] Add more vHBA related tests and module-arize the code
by John Ferlan
Don't be scared off by the quantity of patches...
There's quite a bit of code motion and function renaming going on before
being able to more easily add tests that will ensure that from a nodedev
perspective creation and deletion of the vHBA will work properly and it's
possible to test the various ways to create a vHBA (nothing provide, a
parent by name provided, a parent by wwnn/wwpn provided, and a parent
by fabric_wwn provided).
I did run this through the coverity checking code with no errors...
John Ferlan (15):
tests: Alter test_driver HBA name/data to be closer to reality
test: Add new NPIV capable HBA and a vHBA
test: Add helper to create vHBA for testNodeDeviceCreateXML
tests: Create a more realistic vHBA
test: Fix fchosttest resource leak
util: Create a new virvhba module and move/rename API's
util: Move/rename virStoragePoolGetVhbaSCSIHostParent to virvhba
util: Reduce complexity of virVHBAGetParent
util: Move scsi_host specific functions from virutil
tests: Add new fchosttest tests for management of a vHBA
nodedev: Keep the node device lock longer in nodeDeviceDestroy
nodedev: Rework virNodeDeviceGetParentHost
tests: Add createVHBAByNodeDevice-no-parent to fchosttest
tests: Add createVHBAByNodeDevice-parent-wwn to fchosttest
tests: Add createVHBAByNodeDevice-parent-fabric-wwn to fchosttest
po/POTFILES.in | 2 +
src/Makefile.am | 2 +
src/conf/node_device_conf.c | 76 +++-
src/conf/node_device_conf.h | 19 +-
src/conf/storage_conf.c | 100 ++---
src/conf/storage_conf.h | 5 -
src/libvirt_private.syms | 32 +-
src/node_device/node_device_driver.c | 92 ++--
src/node_device/node_device_linux_sysfs.c | 24 +-
src/storage/storage_backend_scsi.c | 68 +--
src/test/test_driver.c | 178 ++++++--
src/util/virscsi.c | 4 +
src/util/virscsihost.c | 297 ++++++++++++
src/util/virscsihost.h | 40 ++
src/util/virutil.c | 724 ------------------------------
src/util/virutil.h | 47 --
src/util/virvhba.c | 591 ++++++++++++++++++++++++
src/util/virvhba.h | 59 +++
tests/fchosttest.c | 183 ++++++--
tests/objecteventtest.c | 6 +-
tests/scsihosttest.c | 16 +-
tests/virrandommock.c | 9 +
22 files changed, 1463 insertions(+), 1111 deletions(-)
create mode 100644 src/util/virscsihost.c
create mode 100644 src/util/virscsihost.h
create mode 100644 src/util/virvhba.c
create mode 100644 src/util/virvhba.h
--
2.7.4
7 years, 10 months
[libvirt] [PATCH v2 00/12] qemu: migration: show disks stats for nbd migration
by Nikolay Shirokovskiy
diff from v1:
============
1. patch "qemu: clean out unused migrate to unix" is dropped
as it is already pushed.
2. a lot of refactoring patches added, namely all except
the last patch.
3. fetching mirroring stats is done separately from getting
migration status. Generally speaking refactorings patches
removes the function to fetch migrations status altogether.
Current migration stats will show something like [1] when in
the process of mirroring of non shared disks. This gives very
little info on the migration progress. Likewise completed stats miss
disks mirroring info.
This patch provides disks stats in the said phase like in [2] so
user can now understand what's going on. However data stats miss
memory stats, so data total and remaining will change when memory
migration starts.
AFAIU disks stats were available before the nbd based migration
becomes the default. So this patch returns disks stats back at
some level.
[1]
Job type: Unbounded
Time elapsed: 4964 ms
[2]
Job type: Unbounded
Time elapsed: 4964 ms
Data processed: 146.000 MiB
Data remaining: 854.000 MiB
Data total: 1000.000 MiB
File processed: 146.000 MiB
File remaining: 854.000 MiB
File total: 1000.000 MiB
Nikolay Shirokovskiy (12):
qemu: qemuDomainJobInfoToParams drop unused code
qemu: introduce qemu domain job status
qemu: introduce QEMU_DOMAIN_JOB_STATUS_POSTCOPY
qemu: drop QEMU_MIGRATION_COMPLETED_UPDATE_STATS
qemu: drop excessive zero-out in qemuMigrationFetchJobStatus
qemu: drop fetch and update status functions
qemu: simplify getting completed job stats
qemu: drop unused code in qemuDomainGetJobStatsInternal
qemu: drop fetch flag in qemuDomainGetJobStatsInternal
qemu: split getting stats for migration and others
qemu: introduce QEMU_DOMAIN_JOB_STATUS_PREPARE
qemu: show disks stats for nbd migration
docs/news.html.in | 4 +
src/qemu/qemu_domain.c | 32 ++++++--
src/qemu/qemu_domain.h | 13 +++-
src/qemu/qemu_driver.c | 100 ++++++++++++++----------
src/qemu/qemu_migration.c | 195 ++++++++++++++++++++++++++--------------------
src/qemu/qemu_migration.h | 8 +-
src/qemu/qemu_process.c | 6 +-
7 files changed, 214 insertions(+), 144 deletions(-)
--
1.8.3.1
7 years, 10 months
[libvirt] [RFC PATCH 00/10] introduce push backups
by Nikolay Shirokovskiy
Push backup is a backup when hypervisor itself copy backup
data to destination in contrast to pull backup when hypervisor
exports backup data thru some interface and mgmt itself make
a copy.
This patch series basically adds API and remote/qemu implementation
of backup creation and correspondent backup xml description definition.
Just like other blockjobs backup creation is asynchronous. That
is creation is merely a backup start and client should track
backup error/completion thru blockjob events. Another option
is to make backup synchronus operation. AFAIU on this way we
have to make backup asynchronus job and thus make all modifying
commands unavailable during backup. This makes backup rather
obtrusive operation which is not convinient.
Backup xml desription follows closely snapshot one and
is described in more details in definition patch [1].
Nikolay Shirokovskiy (10):
api: add API to create backup
add driver based implementation of backup API
remote: add backup API
qemu: monitor: add backup command
misc: add backup block job type
conf: add backup definition [1]
qemu: add qemuDomainBackupCreateXML implementation
qemu: check backup destination before start
qemu: prepare backup destination
virsh: add create backup command
daemon/remote.c | 8 +
examples/object-events/event-test.c | 3 +
include/libvirt/libvirt-domain-backup.h | 59 +++++++
include/libvirt/libvirt-domain.h | 3 +
include/libvirt/libvirt.h | 1 +
include/libvirt/virterror.h | 2 +
po/POTFILES.in | 2 +
src/Makefile.am | 3 +
src/access/viraccessperm.c | 3 +-
src/access/viraccessperm.h | 6 +
src/conf/backup_conf.c | 294 ++++++++++++++++++++++++++++++++
src/conf/backup_conf.h | 69 ++++++++
src/conf/domain_conf.c | 2 +-
src/datatypes.c | 60 +++++++
src/datatypes.h | 29 ++++
src/driver-hypervisor.h | 6 +
src/libvirt-domain-backup.c | 203 ++++++++++++++++++++++
src/libvirt_private.syms | 9 +
src/libvirt_public.syms | 10 ++
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_domain.c | 14 ++
src/qemu/qemu_domain.h | 2 +
src/qemu/qemu_driver.c | 249 +++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 13 ++
src/qemu/qemu_monitor.h | 5 +
src/qemu/qemu_monitor_json.c | 36 ++++
src/qemu/qemu_monitor_json.h | 6 +
src/remote/remote_driver.c | 7 +
src/remote/remote_protocol.x | 24 ++-
src/rpc/gendispatch.pl | 29 +++-
src/util/virerror.c | 6 +
tools/Makefile.am | 1 +
tools/virsh-backup.c | 101 +++++++++++
tools/virsh-backup.h | 29 ++++
tools/virsh-domain.c | 3 +-
tools/virsh.c | 2 +
tools/virsh.h | 1 +
37 files changed, 1290 insertions(+), 11 deletions(-)
create mode 100644 include/libvirt/libvirt-domain-backup.h
create mode 100644 src/conf/backup_conf.c
create mode 100644 src/conf/backup_conf.h
create mode 100644 src/libvirt-domain-backup.c
create mode 100644 tools/virsh-backup.c
create mode 100644 tools/virsh-backup.h
--
1.8.3.1
7 years, 10 months
[libvirt] [PATCH 0/9] perf: Add software perf events
by Nitesh Konkar
This patch series adds software perf events.
Nitesh Konkar (9):
perf: add cpu_clock software perf event support
perf: add task_clock software perf event support
perf: add page_faults software perf event support
perf: add context_switches software perf event support
perf: add cpu_migrations software perf event support
perf: add page_faults_min software perf event support
perf: add page_faults_maj software perf event support
perf: add alignment_faults software perf event support
perf: add emulation_faults software perf event support
docs/formatdomain.html.in | 58 +++++++++++++++++++
docs/news.xml | 7 ++-
docs/schemas/domaincommon.rng | 9 +++
include/libvirt/libvirt-domain.h | 90 +++++++++++++++++++++++++++++
src/libvirt-domain.c | 24 ++++++++
src/qemu/qemu_driver.c | 9 +++
src/util/virperf.c | 33 ++++++++++-
src/util/virperf.h | 9 +++
tests/genericxml2xmlindata/generic-perf.xml | 9 +++
tools/virsh.pod | 35 +++++++++++
10 files changed, 280 insertions(+), 3 deletions(-)
--
1.9.3
7 years, 10 months
[libvirt] [PATCH] Validate required CPU features even for host-passthrough
by Ján Tomko
Commit adff345 allowed enabling features with -cpu host
without ajdusting the validity checks on domain startup
and migration.
---
src/qemu/qemu_migration.c | 2 +-
src/qemu/qemu_process.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 0f4a6cf..0db1616 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2322,7 +2322,7 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver,
if (!qemuMigrationIsAllowedHostdev(vm->def))
return false;
- if (vm->def->cpu && vm->def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
+ if (vm->def->cpu) {
for (i = 0; i < vm->def->cpu->nfeatures; i++) {
virCPUFeatureDefPtr feature = &vm->def->cpu->features[i];
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 184440d..2ad6451 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3819,7 +3819,7 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver,
}
}
- if (def->cpu && def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
+ if (def->cpu) {
for (i = 0; i < def->cpu->nfeatures; i++) {
virCPUFeatureDefPtr feature = &def->cpu->features[i];
--
2.10.2
7 years, 10 months
[libvirt] [PATCH] qemu: Filter ARAT CPU feature from host-model
by Jiri Denemark
ARAT feature was first introduced in QEMU 2.4.0, which means host-model
CPU mode is unusable with QEMU < 2.4.0 on any host CPU which supports
ARAT. Let's not include this feature in host-model CPUs unless a user
explicitly asks for it.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
We will do this properly in the future since we will ask QEMU what CPU
features it understands and what it thinks about host CPU. However, the
required QMP interface is not upstream yet.
src/qemu/qemu_capabilities.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index cfd090c3f..2da4c76ab 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2959,7 +2959,8 @@ virQEMUCapsCPUFilterFeatures(const char *name,
{
if (STREQ(name, "cmt") ||
STREQ(name, "mbm_total") ||
- STREQ(name, "mbm_local"))
+ STREQ(name, "mbm_local") ||
+ STREQ(name, "arat"))
return false;
return true;
--
2.11.0.rc2
7 years, 10 months
[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, 10 months