[libvirt] [PATCH go-xml] Add support for CPUTune in Domain
by Michal Rostecki
From: Michal Rostecki <michal.rostecki(a)gmail.com>
Signed-off-by: Victoria Efimova <neverpushthisbutton(a)yandex.ru>
Signed-off-by: Ivan Shvedunov <ischvedunov(a)mirantis.com>
Signed-off-by: Miha Pleško <miha.plesko(a)xlab.si>
Signed-off-by: Michal Rostecki <michal.rostecki(a)gmail.com>
---
domain.go | 19 +++++++++++++++++++
domain_test.go | 20 ++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/domain.go b/domain.go
index bacab11..3efd68c 100644
--- a/domain.go
+++ b/domain.go
@@ -722,6 +722,24 @@ type DomainFeatureList struct {
SMM *DomainFeatureState `xml:"smm"`
}
+type DomainCPUTuneShares struct {
+ Value uint `xml:",chardata"`
+}
+
+type DomainCPUTunePeriod struct {
+ Value uint64 `xml:",chardata"`
+}
+
+type DomainCPUTuneQuota struct {
+ Value int64 `xml:",chardata"`
+}
+
+type DomainCPUTune struct {
+ Shares *DomainCPUTuneShares `xml:"shares"`
+ Period *DomainCPUTunePeriod `xml:"period"`
+ Quota *DomainCPUTuneQuota `xml:"quota"`
+}
+
type DomainQEMUCommandlineArg struct {
Value string `xml:"value,attr"`
}
@@ -751,6 +769,7 @@ type Domain struct {
MemoryBacking *DomainMemoryBacking `xml:"memoryBacking"`
VCPU *DomainVCPU `xml:"vcpu"`
VCPUs *DomainVCPUs `xml:"vcpus"`
+ CPUTune *DomainCPUTune `xml:"cputune"`
Resource *DomainResource `xml:"resource"`
SysInfo *DomainSysInfo `xml:"sysinfo"`
OS *DomainOS `xml:"os"`
diff --git a/domain_test.go b/domain_test.go
index dbebe42..b427b50 100644
--- a/domain_test.go
+++ b/domain_test.go
@@ -1335,6 +1335,26 @@ var domainTestData = []struct {
`</domain>`,
},
},
+ {
+ Object: &Domain{
+ Name: "test",
+ CPUTune: &DomainCPUTune{
+ Shares: &DomainCPUTuneShares{Value: 1024},
+ Period: &DomainCPUTunePeriod{Value: 500000},
+ Quota: &DomainCPUTuneQuota{Value: -1},
+ },
+ },
+ Expected: []string{
+ `<domain>`,
+ ` <name>test</name>`,
+ ` <cputune>`,
+ ` <shares>1024</shares>`,
+ ` <period>500000</period>`,
+ ` <quota>-1</quota>`,
+ ` </cputune>`,
+ `</domain>`,
+ },
+ },
/* Tests for sub-documents that can be hotplugged */
{
--
2.13.6
7 years
[libvirt] [PATCH go-xml] Add bootp option to NetworkDHCP
by Michal Rostecki
From: Michal Rostecki <michal.rostecki(a)gmail.com>
Support specyfing concrete file and TFTP server
for PXE boot.
Signed-off-by: Michal Rostecki <michal.rostecki(a)gmail.com>
---
network.go | 6 ++++++
network_test.go | 7 +++++++
2 files changed, 13 insertions(+)
diff --git a/network.go b/network.go
index 32f125a..10c4dfc 100644
--- a/network.go
+++ b/network.go
@@ -78,9 +78,15 @@ type NetworkDHCPHost struct {
IP string `xml:"ip,attr,omitempty"`
}
+type NetworkBootp struct {
+ File string `xml:"file,attr,omitempty"`
+ Server string `xml:"server,attr,omitempty"`
+}
+
type NetworkDHCP struct {
Ranges []NetworkDHCPRange `xml:"range"`
Hosts []NetworkDHCPHost `xml:"host"`
+ Bootp []NetworkBootp `xml:"bootp"`
}
type NetworkIP struct {
diff --git a/network_test.go b/network_test.go
index b1bd168..3efb278 100644
--- a/network_test.go
+++ b/network_test.go
@@ -100,6 +100,12 @@ var networkTestData = []struct {
IP: "192.168.122.10",
},
},
+ Bootp: []NetworkBootp{
+ NetworkBootp{
+ File: "pxelinux.0",
+ Server: "192.168.122.1",
+ },
+ },
},
},
NetworkIP{
@@ -179,6 +185,7 @@ var networkTestData = []struct {
` <dhcp>`,
` <range start="192.168.122.2" end="192.168.122.254"></range>`,
` <host mac="00:16:3e:77:e2:ed" name="foo.example.com" ip="192.168.122.10"></host>`,
+ ` <bootp file="pxelinux.0" server="192.168.122.1"></bootp>`,
` </dhcp>`,
` </ip>`,
` <ip address="2001:db8:ca2:2::1" family="ipv6" prefix="64">`,
--
2.13.6
7 years
[libvirt] [jenkins-ci PATCH] projects: disable libvirt-perl RPM build on centos-6
by Pavel Hrdina
There is no perl-CPAN-Changes package.
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
Pushed under trivial rule.
projects/libvirt-perl.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/projects/libvirt-perl.yaml b/projects/libvirt-perl.yaml
index 77bc4ea..665befd 100644
--- a/projects/libvirt-perl.yaml
+++ b/projects/libvirt-perl.yaml
@@ -21,7 +21,6 @@
- perl-makemaker-rpm-job:
parent_jobs: 'libvirt-perl-master-test'
machines:
- - libvirt-centos-6
- libvirt-centos-7
- libvirt-fedora-25
- libvirt-fedora-26
--
2.13.6
7 years
[libvirt] [PATCH go-xml] Add address support for memory device
by zhenwei.pi
Add Base element for DomainAddress.
Add address element for DomainMemorydev.
Add test code for new DomainMemorydev.
Signed-off-by: zhenwei.pi <zhenwei.pi(a)youruncloud.com>
---
domain.go | 2 ++
domain_test.go | 9 +++++++++
2 files changed, 11 insertions(+)
diff --git a/domain.go b/domain.go
index bacab11..3d9404f 100644
--- a/domain.go
+++ b/domain.go
@@ -297,6 +297,7 @@ type DomainAddress struct {
Function *HexUint `xml:"function,attr"`
Target *uint `xml:"target,attr"`
Unit *uint `xml:"unit,attr"`
+ Base *HexUint `xml:"base,attr"`
}
type DomainConsole struct {
@@ -450,6 +451,7 @@ type DomainMemorydev struct {
Model string `xml:"model,attr"`
Access string `xml:"access,attr"`
Target *DomainMemorydevTarget `xml:"target"`
+ Address *DomainAddress `xml:"address"`
}
type DomainDeviceList struct {
diff --git a/domain_test.go b/domain_test.go
index dbebe42..cbc5d7f 100644
--- a/domain_test.go
+++ b/domain_test.go
@@ -66,6 +66,9 @@ var vcpuId0 uint = 0
var vcpuOrder0 uint = 1
var vcpuId1 uint = 1
+var memorydevAddressSlot HexUint = 0
+var memorydevAddressBase HexUint = 4294967296
+
var domainTestData = []struct {
Object Document
Expected []string
@@ -385,6 +388,11 @@ var domainTestData = []struct {
Value: 0,
},
},
+ Address: &DomainAddress{
+ Type: "dimm",
+ Slot: &memorydevAddressSlot,
+ Base: &memorydevAddressBase,
+ },
},
},
},
@@ -434,6 +442,7 @@ var domainTestData = []struct {
` <size unit="GiB">1</size>`,
` <node>0</node>`,
` </target>`,
+ ` <address type="dimm" slot="0" base="4294967296"></address>`,
` </memory>`,
` </devices>`,
`</domain>`,
--
2.7.4
7 years
[libvirt] [jenkins-ci PATCH 0/7] several fixes
by Pavel Hrdina
Pavel Hrdina (7):
projects: make sure that we use correct make for all projects
projects: run RPM builds only on systems where it makes sense
projects: build osinfo-db on debian-8
jobs: projects: be explicit about python2 binary
guests: install unzip for virt-manager
guests: install libgovirt-devel on all RPM based distros
projects: disable libvirt-sandbox on centos-7
guests/vars/mappings.yml | 6 +++++-
guests/vars/projects/virt-manager.yml | 1 +
jobs/python-distutils.yaml | 8 ++++----
projects/libosinfo.yaml | 5 +++++
projects/libvirt-cim.yaml | 8 +++++---
projects/libvirt-glib.yaml | 5 +++++
projects/libvirt-perl.yaml | 6 ++++++
projects/libvirt-python.yaml | 6 ++++++
projects/libvirt-sandbox.yaml | 5 ++++-
projects/libvirt-tck.yaml | 4 ++++
projects/osinfo-db-tools.yaml | 5 +++++
projects/osinfo-db.yaml | 16 ++++++++++++----
projects/virt-manager.yaml | 7 ++++++-
projects/virt-viewer.yaml | 3 +++
14 files changed, 71 insertions(+), 14 deletions(-)
--
2.13.6
7 years
[libvirt] [PATCH v2] spec: Restart libvirtd in posttrans
by Jiri Denemark
When upgrading libvirt packages, there's no strict ordering for the
installation or removal of the individual libvirt sub packages. Thus
libvirt-daemon may be upgraded (and its %postun scriptlet) started
before all sub packages with driver libraries are upgraded. When
libvirt-daemon's %postun scriptlet restarts the daemon old drivers may
still be laying around and the daemon may crash when it tries to use
them.
Let's restart the daemon in %posttrans to make sure libvirtd is
restarted only after all sub packages are at the same version.
https://bugzilla.redhat.com/show_bug.cgi?id=1464300
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
libvirt.spec.in | 37 ++++++++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 7 deletions(-)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 0123d0655..b00689cab 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1516,6 +1516,10 @@ fi
/sbin/chkconfig --add virtlockd
%endif
+# request daemon restart in posttrans
+mkdir -p %{_localstatedir}/lib/rpm-state/libvirt || :
+touch %{_localstatedir}/lib/rpm-state/libvirt/restart || :
+
%preun daemon
%if %{with_systemd}
%if %{with_systemd_macros}
@@ -1554,13 +1558,11 @@ fi
if [ $1 -ge 1 ] ; then
/bin/systemctl reload-or-try-restart virtlockd.service >/dev/null 2>&1 || :
/bin/systemctl reload-or-try-restart virtlogd.service >/dev/null 2>&1 || :
- /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || :
fi
%else
if [ $1 -ge 1 ]; then
/sbin/service virtlockd reload > /dev/null 2>&1 || :
/sbin/service virtlogd reload > /dev/null 2>&1 || :
- /sbin/service libvirtd condrestart > /dev/null 2>&1
fi
%endif
@@ -1570,7 +1572,6 @@ fi
if [ "$1" -ge "1" ]; then
/sbin/service virtlockd reload > /dev/null 2>&1 || :
/sbin/service virtlogd reload > /dev/null 2>&1 || :
- /sbin/service libvirtd condrestart > /dev/null 2>&1
fi
%endif
@@ -1593,6 +1594,16 @@ if [ $1 -ge 1 ] ; then
%endif
fi
+%posttrans daemon
+if [ -f %{_localstatedir}/lib/rpm-state/libvirt/restart ]; then
+%if %{with_systemd}
+ /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || :
+%else
+ /sbin/service libvirtd condrestart > /dev/null 2>&1 || :
+%endif
+fi
+rm -rf %{_localstatedir}/lib/rpm-state/libvirt || :
+
%post daemon-config-network
if test $1 -eq 1 && test ! -f %{_sysconfdir}/libvirt/qemu/networks/default.xml ; then
# see if the network used by default network creates a conflict,
@@ -1631,23 +1642,35 @@ if test $1 -eq 1 && test ! -f %{_sysconfdir}/libvirt/qemu/networks/default.xml ;
ln -s ../default.xml %{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
# Make sure libvirt picks up the new network defininiton
+ mkdir -p %{_localstatedir}/lib/rpm-state/libvirt || :
+ touch %{_localstatedir}/lib/rpm-state/libvirt/restart || :
+fi
+
+%posttrans daemon-config-network
+if [ -f %{_localstatedir}/lib/rpm-state/libvirt/restart ]; then
%if %{with_systemd}
- /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 ||:
+ /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || :
%else
/sbin/service libvirtd condrestart > /dev/null 2>&1 || :
%endif
-
fi
-
+rm -rf %{_localstatedir}/lib/rpm-state/libvirt || :
%post daemon-config-nwfilter
cp %{_datadir}/libvirt/nwfilter/*.xml %{_sysconfdir}/libvirt/nwfilter/
# Make sure libvirt picks up the new nwfilter defininitons
+mkdir -p %{_localstatedir}/lib/rpm-state/libvirt || :
+touch %{_localstatedir}/lib/rpm-state/libvirt/restart || :
+
+%posttrans daemon-config-nwfilter
+if [ -f %{_localstatedir}/lib/rpm-state/libvirt/restart ]; then
%if %{with_systemd}
- /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 ||:
+ /bin/systemctl try-restart libvirtd.service >/dev/null 2>&1 || :
%else
/sbin/service libvirtd condrestart > /dev/null 2>&1 || :
%endif
+fi
+rm -rf %{_localstatedir}/lib/rpm-state/libvirt || :
%if %{with_systemd}
--
2.14.3
7 years
[libvirt] [PATCH RFC v2] lib: provide error message in new block job error event
by Nikolay Shirokovskiy
If block job is completed with error qemu additionally
provides error message. This patch introduces new event
VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR to pass error message to client.
This error message has no semantics and should not be interpreted.
API and RPC layer also have reserved 'code' field to pass semantics
loaded error code value in the future.
---
The patch is applied on top of [1] patch series (not yet pushed though).
Diff from v1 [2]:
1. Replace block job event version 3 with block job error event.
2. Add code field to API/RPC to pass error code in the future.
Peter, I decided not to use enum/union as this looks like to much effort to extend
code generation for this simple case. Using typed params looks unsuitable too.
[1] https://www.redhat.com/archives/libvir-list/2017-October/msg01292.html
[2] https://www.redhat.com/archives/libvir-list/2017-October/msg01369.html
daemon/remote.c | 48 +++++++++++++++++++
examples/object-events/event-test.c | 20 ++++++++
include/libvirt/libvirt-domain.h | 25 ++++++++++
src/conf/domain_event.c | 96 +++++++++++++++++++++++++++++++++++++
src/conf/domain_event.h | 13 +++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_blockjob.c | 9 +++-
src/qemu/qemu_blockjob.h | 3 +-
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 10 ++--
src/qemu/qemu_process.c | 12 +++--
src/remote/remote_driver.c | 34 +++++++++++++
src/remote/remote_protocol.x | 17 ++++++-
src/remote_protocol-structs | 9 ++++
tools/virsh-domain.c | 24 ++++++++++
15 files changed, 313 insertions(+), 10 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 3f7d2d3..545bf67 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -1342,6 +1342,53 @@ remoteRelayDomainEventBlockThreshold(virConnectPtr conn,
}
+static int
+remoteRelayDomainEventBlockJobError(virConnectPtr conn,
+ virDomainPtr dom,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message,
+ void *opaque)
+{
+ daemonClientEventCallbackPtr callback = opaque;
+ remote_domain_event_block_job_error_msg msg;
+
+ if (callback->callbackID < 0 ||
+ !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+ return -1;
+
+ VIR_DEBUG("Relaying domain block job error event %s %d %s %i %u %s, callback %d",
+ dom->name, dom->id, dev, type, code, NULLSTR(message),
+ callback->callbackID);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.callbackID = callback->callbackID;
+ if (VIR_STRDUP(msg.dev, dev) < 0)
+ return -1;
+ if (message) {
+ if (VIR_ALLOC(msg.message) < 0 ||
+ VIR_STRDUP(*(msg.message), message) < 0)
+ goto error;
+ }
+ msg.type = type;
+ msg.code = code;
+ make_nonnull_domain(&msg.dom, dom);
+
+ remoteDispatchObjectEventSend(callback->client, remoteProgram,
+ REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR,
+ (xdrproc_t)xdr_remote_domain_event_block_job_error_msg,
+ &msg);
+ return 0;
+
+ error:
+ VIR_FREE(msg.dev);
+ VIR_FREE(msg.message);
+
+ return -1;
+}
+
+
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -1368,6 +1415,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemovalFailed),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMetadataChange),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold),
+ VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJobError),
};
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 a144638..43a3878 100644
--- a/examples/object-events/event-test.c
+++ b/examples/object-events/event-test.c
@@ -936,6 +936,25 @@ myDomainEventBlockJobCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
static int
+myDomainEventBlockJobErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message,
+ void *opaque)
+{
+ const char *eventName = opaque;
+
+ printf("%s EVENT: Domain %s(%d) block job error callback '%s' disk '%s', "
+ "type '%s' code '%u' message '%s'",
+ __func__, virDomainGetName(dom), virDomainGetID(dom), eventName,
+ dev, blockJobTypeToStr(type), code, NULLSTR(message));
+ return 0;
+}
+
+
+static int
myDomainEventBlockThresholdCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainPtr dom,
const char *dev,
@@ -1082,6 +1101,7 @@ struct domainEventData domainEvents[] = {
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback),
+ DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR, myDomainEventBlockJobErrorCallback),
};
struct storagePoolEventData {
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 4048acf..9f5c1ba 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4363,6 +4363,30 @@ typedef void (*virConnectDomainEventBlockThresholdCallback)(virConnectPtr conn,
unsigned long long excess,
void *opaque);
+
+/**
+ * virConnectDomainEventBlockJobErrorCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @dev: name associated with the affected disk or storage backing chain
+ * element
+ * @type: type of block job (virDomainBlockJobType)
+ * @code: always 0, reserved for future use
+ * @message: error message with no semantics, can be NULL
+ * @opaque: application specified data
+ *
+ * The callback occurs when block job is completed with error and provides
+ * error message in @message.
+ *
+ */
+typedef void (*virConnectDomainEventBlockJobErrorCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message,
+ void *opaque);
+
/**
* VIR_DOMAIN_EVENT_CALLBACK:
*
@@ -4405,6 +4429,7 @@ typedef enum {
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED = 22, /* virConnectDomainEventDeviceRemovalFailedCallback */
VIR_DOMAIN_EVENT_ID_METADATA_CHANGE = 23, /* virConnectDomainEventMetadataChangeCallback */
VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback */
+ VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR = 25, /* virConnectDomainEventBlockJobErrorCallback */
# ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_EVENT_ID_LAST
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index 7baccd5..3a98de7 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -47,6 +47,7 @@ static virClassPtr virDomainEventWatchdogClass;
static virClassPtr virDomainEventIOErrorClass;
static virClassPtr virDomainEventGraphicsClass;
static virClassPtr virDomainEventBlockJobClass;
+static virClassPtr virDomainEventBlockJobErrorClass;
static virClassPtr virDomainEventDiskChangeClass;
static virClassPtr virDomainEventTrayChangeClass;
static virClassPtr virDomainEventBalloonChangeClass;
@@ -69,6 +70,7 @@ static void virDomainEventWatchdogDispose(void *obj);
static void virDomainEventIOErrorDispose(void *obj);
static void virDomainEventGraphicsDispose(void *obj);
static void virDomainEventBlockJobDispose(void *obj);
+static void virDomainEventBlockJobErrorDispose(void *obj);
static void virDomainEventDiskChangeDispose(void *obj);
static void virDomainEventTrayChangeDispose(void *obj);
static void virDomainEventBalloonChangeDispose(void *obj);
@@ -151,6 +153,17 @@ struct _virDomainEventBlockJob {
typedef struct _virDomainEventBlockJob virDomainEventBlockJob;
typedef virDomainEventBlockJob *virDomainEventBlockJobPtr;
+struct _virDomainEventBlockJobError {
+ virDomainEvent parent;
+
+ char *dev;
+ int type;
+ unsigned int code;
+ char *message;
+};
+typedef struct _virDomainEventBlockJobError virDomainEventBlockJobError;
+typedef virDomainEventBlockJobError *virDomainEventBlockJobErrorPtr;
+
struct _virDomainEventGraphics {
virDomainEvent parent;
@@ -337,6 +350,12 @@ virDomainEventsOnceInit(void)
sizeof(virDomainEventBlockJob),
virDomainEventBlockJobDispose)))
return -1;
+ if (!(virDomainEventBlockJobErrorClass =
+ virClassNew(virDomainEventClass,
+ "virDomainEventBlockJobError",
+ sizeof(virDomainEventBlockJobError),
+ virDomainEventBlockJobErrorDispose)))
+ return -1;
if (!(virDomainEventDiskChangeClass =
virClassNew(virDomainEventClass,
"virDomainEventDiskChange",
@@ -504,6 +523,16 @@ virDomainEventBlockJobDispose(void *obj)
}
static void
+virDomainEventBlockJobErrorDispose(void *obj)
+{
+ virDomainEventBlockJobErrorPtr event = obj;
+ VIR_DEBUG("obj=%p", event);
+
+ VIR_FREE(event->dev);
+ VIR_FREE(event->message);
+}
+
+static void
virDomainEventDiskChangeDispose(void *obj)
{
virDomainEventDiskChangePtr event = obj;
@@ -1061,6 +1090,59 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom,
dst, type, status);
}
+static virObjectEventPtr
+virDomainEventBlockJobErrorNew(int id,
+ const char *name,
+ unsigned char *uuid,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message)
+{
+ virDomainEventBlockJobErrorPtr ev;
+
+ if (virDomainEventsInitialize() < 0)
+ return NULL;
+
+ if (!(ev = virDomainEventNew(virDomainEventBlockJobErrorClass,
+ VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR,
+ id, name, uuid)))
+ return NULL;
+
+ if (VIR_STRDUP(ev->dev, dev) < 0) {
+ virObjectUnref(ev);
+ return NULL;
+ }
+ ignore_value(VIR_STRDUP_QUIET(ev->message, message));
+ ev->type = type;
+ ev->code = code;
+
+ return (virObjectEventPtr)ev;
+}
+
+virObjectEventPtr
+virDomainEventBlockJobErrorNewFromObj(virDomainObjPtr obj,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message)
+{
+ return virDomainEventBlockJobErrorNew(obj->def->id, obj->def->name,
+ obj->def->uuid, dev, type, code,
+ message);
+}
+
+virObjectEventPtr
+virDomainEventBlockJobErrorNewFromDom(virDomainPtr dom,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message)
+{
+ return virDomainEventBlockJobErrorNew(dom->id, dom->name, dom->uuid,
+ dev, type, code, message);
+}
+
virObjectEventPtr
virDomainEventControlErrorNewFromDom(virDomainPtr dom)
{
@@ -1871,6 +1953,20 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
goto cleanup;
}
+ case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_ERROR:
+ {
+ virDomainEventBlockJobErrorPtr blockJobErrorEvent;
+
+ blockJobErrorEvent = (virDomainEventBlockJobErrorPtr)event;
+ ((virConnectDomainEventBlockJobErrorCallback)cb)(conn, dom,
+ blockJobErrorEvent->dev,
+ blockJobErrorEvent->type,
+ blockJobErrorEvent->code,
+ blockJobErrorEvent->message,
+ cbopaque);
+ goto cleanup;
+ }
+
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
{
virDomainEventDiskChangePtr diskChangeEvent;
diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
index 3992a29..456026c 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -138,6 +138,19 @@ virDomainEventBlockJob2NewFromDom(virDomainPtr dom,
int status);
virObjectEventPtr
+virDomainEventBlockJobErrorNewFromObj(virDomainObjPtr obj,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message);
+virObjectEventPtr
+virDomainEventBlockJobErrorNewFromDom(virDomainPtr dom,
+ const char *dev,
+ int type,
+ unsigned int code,
+ const char *message);
+
+virObjectEventPtr
virDomainEventDiskChangeNewFromObj(virDomainObjPtr obj,
const char *oldSrcPath,
const char *newSrcPath,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 448d962..594c792 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -562,6 +562,8 @@ virDomainEventBalloonChangeNewFromDom;
virDomainEventBalloonChangeNewFromObj;
virDomainEventBlockJob2NewFromDom;
virDomainEventBlockJob2NewFromObj;
+virDomainEventBlockJobErrorNewFromDom;
+virDomainEventBlockJobErrorNewFromObj;
virDomainEventBlockJobNewFromDom;
virDomainEventBlockJobNewFromObj;
virDomainEventBlockThresholdNewFromDom;
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 0b1616a..7edc30a 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -70,7 +70,8 @@ qemuBlockJobUpdate(virQEMUDriverPtr driver,
if (status != -1) {
qemuBlockJobEventProcess(driver, vm, disk, asyncJob,
diskPriv->blockJobType,
- diskPriv->blockJobStatus);
+ diskPriv->blockJobStatus,
+ diskPriv->blockJobError);
diskPriv->blockJobStatus = -1;
if (error)
VIR_STEAL_PTR(*error, diskPriv->blockJobError);
@@ -100,10 +101,12 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk,
qemuDomainAsyncJob asyncJob,
int type,
- int status)
+ int status,
+ const char *error)
{
virObjectEventPtr event = NULL;
virObjectEventPtr event2 = NULL;
+ virObjectEventPtr event3 = NULL;
const char *path;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainDiskDefPtr persistDisk = NULL;
@@ -123,6 +126,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
path = virDomainDiskGetSource(disk);
event = virDomainEventBlockJobNewFromObj(vm, path, type, status);
event2 = virDomainEventBlockJob2NewFromObj(vm, disk->dst, type, status);
+ event3 = virDomainEventBlockJobErrorNewFromObj(vm, disk->dst, type, 0, error);
/* If we completed a block pull or commit, then update the XML
* to match. */
@@ -212,6 +216,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
qemuDomainEventQueue(driver, event);
qemuDomainEventQueue(driver, event2);
+ qemuDomainEventQueue(driver, event3);
virObjectUnref(cfg);
}
diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h
index e71d691..18bcaaa 100644
--- a/src/qemu/qemu_blockjob.h
+++ b/src/qemu/qemu_blockjob.h
@@ -36,7 +36,8 @@ void qemuBlockJobEventProcess(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk,
qemuDomainAsyncJob asyncJob,
int type,
- int status);
+ int status,
+ const char *error);
void qemuBlockJobSyncBegin(virDomainDiskDefPtr disk);
void qemuBlockJobSyncEnd(virQEMUDriverPtr driver,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 735e810..99a71b3 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -457,6 +457,7 @@ struct qemuProcessEvent {
int action;
int status;
void *data;
+ char *error;
};
typedef struct _qemuDomainLogContext qemuDomainLogContext;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 725b46a..c6626bb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4715,7 +4715,8 @@ processBlockJobEvent(virQEMUDriverPtr driver,
virDomainObjPtr vm,
char *diskAlias,
int type,
- int status)
+ int status,
+ char *error)
{
virDomainDiskDefPtr disk;
@@ -4728,12 +4729,14 @@ processBlockJobEvent(virQEMUDriverPtr driver,
}
if ((disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias)))
- qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE, type, status);
+ qemuBlockJobEventProcess(driver, vm, disk, QEMU_ASYNC_JOB_NONE,
+ type, status, error);
endjob:
qemuDomainObjEndJob(driver, vm);
cleanup:
VIR_FREE(diskAlias);
+ VIR_FREE(error);
}
@@ -4815,7 +4818,8 @@ static void qemuProcessEventHandler(void *data, void *opaque)
processBlockJobEvent(driver, vm,
processEvent->data,
processEvent->action,
- processEvent->status);
+ processEvent->status,
+ processEvent->error);
break;
case QEMU_PROCESS_EVENT_MONITOR_EOF:
processMonitorEOFEvent(driver, vm);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4bfad5d..6a3d9bc 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1008,6 +1008,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainDiskDefPtr disk;
qemuDomainDiskPrivatePtr diskPriv;
char *data = NULL;
+ char *errorCopy = NULL;
virObjectLock(vm);
@@ -1018,13 +1019,14 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
goto error;
diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+ ignore_value(VIR_STRDUP_QUIET(errorCopy, error));
+
if (diskPriv->blockJobSync) {
/* We have a SYNC API waiting for this event, dispatch it back */
diskPriv->blockJobType = type;
diskPriv->blockJobStatus = status;
VIR_FREE(diskPriv->blockJobError);
- if (error && VIR_STRDUP_QUIET(diskPriv->blockJobError, error) < 0)
- VIR_WARN("Can not pass error message further: %s", error);
+ VIR_STEAL_PTR(diskPriv->blockJobError, errorCopy);
virDomainObjBroadcast(vm);
} else {
/* there is no waiting SYNC API, dispatch the update to a thread */
@@ -1038,6 +1040,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
processEvent->vm = vm;
processEvent->action = type;
processEvent->status = status;
+ VIR_STEAL_PTR(processEvent->error, errorCopy);
virObjectRef(vm);
if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
@@ -1047,11 +1050,14 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
}
cleanup:
+ VIR_FREE(errorCopy);
virObjectUnlock(vm);
return 0;
error:
- if (processEvent)
+ if (processEvent) {
VIR_FREE(processEvent->data);
+ VIR_FREE(processEvent->error);
+ }
VIR_FREE(processEvent);
goto cleanup;
}
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 06719bb..69d93aa 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -405,6 +405,11 @@ remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_U
virNetClientPtr client ATTRIBUTE_UNUSED,
void *evdata, void *opaque);
+static void
+remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog,
+ virNetClientPtr client,
+ void *evdata, void *opaque);
+
static virNetClientProgramEvent remoteEvents[] = {
{ REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
remoteDomainBuildEventLifecycle,
@@ -611,6 +616,10 @@ static virNetClientProgramEvent remoteEvents[] = {
remoteDomainBuildEventBlockThreshold,
sizeof(remote_domain_event_block_threshold_msg),
(xdrproc_t)xdr_remote_domain_event_block_threshold_msg },
+ { REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR,
+ remoteDomainBuildEventBlockJobError,
+ sizeof(remote_domain_event_block_job_error_msg),
+ (xdrproc_t)xdr_remote_domain_event_block_job_error_msg },
};
static void
@@ -5610,6 +5619,31 @@ remoteDomainBuildEventBlockThreshold(virNetClientProgramPtr prog ATTRIBUTE_UNUSE
}
+static void
+remoteDomainBuildEventBlockJobError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ remote_domain_event_block_job_error_msg *msg = evdata;
+ struct private_data *priv = conn->privateData;
+ virDomainPtr dom;
+ virObjectEventPtr event = NULL;
+
+ dom = get_nonnull_domain(conn, msg->dom);
+ if (!dom)
+ return;
+
+ event = virDomainEventBlockJobErrorNewFromDom(dom, msg->dev, msg->type,
+ msg->code,
+ msg->message ? *msg->message : NULL);
+
+ virObjectUnref(dom);
+
+ remoteEventQueue(priv, event, msg->callbackID);
+}
+
+
static int
remoteStreamSend(virStreamPtr st,
const char *data,
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 0aed252..3aba4a3 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3095,6 +3095,15 @@ struct remote_domain_event_block_job_2_msg {
int status;
};
+struct remote_domain_event_block_job_error_msg {
+ int callbackID;
+ remote_nonnull_domain dom;
+ remote_nonnull_string dev;
+ int type;
+ int code;
+ remote_string message;
+};
+
struct remote_domain_event_block_threshold_msg {
int callbackID;
remote_nonnull_domain dom;
@@ -6120,5 +6129,11 @@ enum remote_procedure {
* @generate: both
* @acl: domain:write
*/
- REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION = 390
+ REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION = 390,
+
+ /**
+ * @generate: none
+ * @acl: none
+ */
+ REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_ERROR = 391
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 59b0ace..29dcfc1 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2535,6 +2535,14 @@ struct remote_domain_event_block_job_2_msg {
int type;
int status;
};
+struct remote_domain_event_block_job_error_msg {
+ int callbackID;
+ remote_nonnull_domain dom;
+ remote_nonnull_string dev;
+ int type;
+ int code;
+ remote_string message;
+};
struct remote_domain_event_block_threshold_msg {
int callbackID;
remote_nonnull_domain dom;
@@ -3262,4 +3270,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_MANAGED_SAVE_GET_XML_DESC = 388,
REMOTE_PROC_DOMAIN_MANAGED_SAVE_DEFINE_XML = 389,
REMOTE_PROC_DOMAIN_SET_LIFECYCLE_ACTION = 390,
+ REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_3 = 391,
};
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 1e33e82..7fec0b3 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13253,6 +13253,28 @@ virshEventBlockThresholdPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
}
+static void
+virshEventBlockJobErrorPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *dev,
+ int type,
+ unsigned int code ATTRIBUTE_UNUSED,
+ const char *message,
+ void *opaque)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferAsprintf(&buf, _("event '%s' for domain %s: %s for %s, "
+ "error: %s\n"),
+ ((virshDomEventData *) opaque)->cb->name,
+ virDomainGetName(dom),
+ virshDomainBlockJobToString(type),
+ dev,
+ NULLSTR(message));
+ virshEventPrint(opaque, &buf);
+}
+
+
static vshEventCallback vshEventCallbacks[] = {
{ "lifecycle",
VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -13302,6 +13324,8 @@ static vshEventCallback vshEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), },
{ "block-threshold",
VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
+ { "block-job-error",
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobErrorPrint), },
};
verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
--
1.8.3.1
7 years