[libvirt] [PATCH] add sendevent command and related APIs
by Lai Jiangshan
Enable libvirt send some events to the guest.
This command currently only supports NMI and key events.
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
daemon/remote.c | 52 +++++++++++++++++++++
daemon/remote_dispatch_args.h | 2
daemon/remote_dispatch_prototypes.h | 16 ++++++
daemon/remote_dispatch_table.h | 10 ++++
include/libvirt/libvirt.h.in | 3 +
src/driver.h | 7 ++
src/esx/esx_driver.c | 2
src/libvirt.c | 88 ++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 2
src/libxl/libxl_driver.c | 2
src/lxc/lxc_driver.c | 2
src/openvz/openvz_driver.c | 2
src/phyp/phyp_driver.c | 4 +
src/qemu/qemu_driver.c | 86 +++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 27 +++++++++++
src/qemu/qemu_monitor.h | 3 +
src/qemu/qemu_monitor_json.c | 68 +++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 3 +
src/qemu/qemu_monitor_text.c | 56 ++++++++++++++++++++++
src/qemu/qemu_monitor_text.h | 2
src/remote/remote_driver.c | 50 ++++++++++++++++++++
src/remote/remote_protocol.c | 22 +++++++++
src/remote/remote_protocol.h | 19 +++++++
src/remote/remote_protocol.x | 14 +++++
src/test/test_driver.c | 2
src/uml/uml_driver.c | 2
src/vbox/vbox_tmpl.c | 2
src/vmware/vmware_driver.c | 2
src/xen/xen_driver.c | 2
src/xenapi/xenapi_driver.c | 2
tools/virsh.c | 56 ++++++++++++++++++++++
31 files changed, 608 insertions(+), 2 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 1700c2d..5f9e78a 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -2836,6 +2836,58 @@ remoteDispatchDomainGetBlkioParameters(struct qemud_server *server
}
static int
+remoteDispatchDomainSendEventNMI(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_send_event_nmi_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainPtr dom;
+
+ dom = get_nonnull_domain(conn, args->dom);
+ if (dom == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainSendEventNMI(dom, args->vcpu) == -1) {
+ virDomainFree(dom);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+ virDomainFree(dom);
+ return 0;
+}
+
+static int
+remoteDispatchDomainSendEventKey(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_send_event_key_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainPtr dom;
+
+ dom = get_nonnull_domain(conn, args->dom);
+ if (dom == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainSendEventKey(dom, args->key) == -1) {
+ virDomainFree(dom);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+ virDomainFree(dom);
+ return 0;
+}
+
+static int
remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
struct qemud_client *client ATTRIBUTE_UNUSED,
virConnectPtr conn,
diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h
index f9537d7..289a42e 100644
--- a/daemon/remote_dispatch_args.h
+++ b/daemon/remote_dispatch_args.h
@@ -178,3 +178,5 @@
remote_domain_migrate_set_max_speed_args val_remote_domain_migrate_set_max_speed_args;
remote_storage_vol_upload_args val_remote_storage_vol_upload_args;
remote_storage_vol_download_args val_remote_storage_vol_download_args;
+ remote_domain_send_event_nmi_args val_remote_domain_send_event_nmi_args;
+ remote_domain_send_event_key_args val_remote_domain_send_event_key_args;
diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h
index 18bf41d..f920193 100644
--- a/daemon/remote_dispatch_prototypes.h
+++ b/daemon/remote_dispatch_prototypes.h
@@ -1618,3 +1618,19 @@ static int remoteDispatchSupportsFeature(
remote_error *err,
remote_supports_feature_args *args,
remote_supports_feature_ret *ret);
+static int remoteDispatchDomainSendEventNMI(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_send_event_nmi_args *args,
+ void *ret);
+static int remoteDispatchDomainSendEventKey(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_send_event_key_args *args,
+ void *ret);
diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h
index b39f7c2..a706b19 100644
--- a/daemon/remote_dispatch_table.h
+++ b/daemon/remote_dispatch_table.h
@@ -1052,3 +1052,13 @@
.args_filter = (xdrproc_t) xdr_remote_storage_vol_download_args,
.ret_filter = (xdrproc_t) xdr_void,
},
+{ /* DomainSendEventNmi => 210 */
+ .fn = (dispatch_fn) remoteDispatchDomainSendEventNMI,
+ .args_filter = (xdrproc_t) xdr_remote_domain_send_event_nmi_args,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
+{ /* DomainSendEventKey => 211 */
+ .fn = (dispatch_fn) remoteDispatchDomainSendEventKey,
+ .args_filter = (xdrproc_t) xdr_remote_domain_send_event_key_args,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index bd36015..adbe482 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2517,6 +2517,9 @@ int virDomainOpenConsole(virDomainPtr dom,
virStreamPtr st,
unsigned int flags);
+int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu);
+int virDomainSendEventKey(virDomainPtr domain, const char *key);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/driver.h b/src/driver.h
index e5f91ca..6caf13f 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -515,6 +515,11 @@ typedef int
virStreamPtr st,
unsigned int flags);
+typedef int
+ (*virDrvDomainSendEventNMI)(virDomainPtr dom, unsigned int vcpu);
+
+typedef int
+ (*virDrvDomainSendEventKey)(virDomainPtr dom, const char *key);
/**
* _virDriver:
@@ -639,6 +644,8 @@ struct _virDriver {
virDrvDomainSnapshotDelete domainSnapshotDelete;
virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand;
virDrvDomainOpenConsole domainOpenConsole;
+ virDrvDomainSendEventNMI domainSendEventNMI;
+ virDrvDomainSendEventKey domainSendEventKey;
};
typedef int
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index deda372..7167712 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -4675,6 +4675,8 @@ static virDriver esxDriver = {
esxDomainSnapshotDelete, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
diff --git a/src/libvirt.c b/src/libvirt.c
index 9bdb4c8..245247f 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5245,6 +5245,94 @@ error:
}
/**
+ * virDomainSendEvnetNMI:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @vcpu: the virtual CPU id to send NMI to
+ *
+ * Send NMI to a special vcpu of the guest
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int virDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu)
+{
+ virConnectPtr conn;
+ VIR_DOMAIN_DEBUG(domain, "vcpu=%u", vcpu);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return (-1);
+ }
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ conn = domain->conn;
+
+ if (conn->driver->domainSendEventNMI) {
+ int ret;
+ ret = conn->driver->domainSendEventNMI(domain, vcpu);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+}
+
+/**
+ * virDomainSendEventKey:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @key: the string of key or key sequence
+ *
+ * Send a special key or key sequence to the guest
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int virDomainSendEventKey(virDomainPtr domain, const char *key)
+{
+ virConnectPtr conn;
+ VIR_DOMAIN_DEBUG(domain, "key=%s", key);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return (-1);
+ }
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ conn = domain->conn;
+
+ if (conn->driver->domainSendEventKey) {
+ int ret;
+ ret = conn->driver->domainSendEventKey(domain, key);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+}
+
+/**
* virDomainSetVcpus:
* @domain: pointer to domain object, or NULL for Domain0
* @nvcpus: the new number of virtual CPUs for this domain
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index b4aed41..cd0f474 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -434,6 +434,8 @@ LIBVIRT_0.9.0 {
virEventRunDefaultImpl;
virStorageVolDownload;
virStorageVolUpload;
+ virDomainSendEventNMI;
+ virDomainSendEventKey;
} LIBVIRT_0.8.8;
# .... define new API here using predicted next version number ....
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index e996ff6..040fc16 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -2353,6 +2353,8 @@ static virDriver libxlDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
static virStateDriver libxlStateDriver = {
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index e905302..1284ab1 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2906,6 +2906,8 @@ static virDriver lxcDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
lxcDomainOpenConsole, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
static virStateDriver lxcStateDriver = {
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index fb30c37..26ba0a5 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -1654,6 +1654,8 @@ static virDriver openvzDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
int openvzRegister(void) {
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 51f9ff6..d5d0ea6 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -4054,7 +4054,9 @@ static virDriver phypDriver = {
NULL, /* domainRevertToSnapshot */
NULL, /* domainSnapshotDelete */
NULL, /* qemuMonitorCommand */
- NULL, /* domainOpenConsole */
+ NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
static virStorageDriver phypStorageDriver = {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index dd12dc8..02af591 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1659,6 +1659,90 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_MEM_LIVE);
}
+static int qemuDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu)
+{
+ struct qemud_driver *driver = domain->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv;
+
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(domain->uuid, uuidstr);
+ qemuReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
+ goto cleanup;
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorSendEventNMI(priv->mon, vcpu);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ if (qemuDomainObjEndJob(vm) == 0) {
+ vm = NULL;
+ goto cleanup;
+ }
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
+static int qemuDomainSendEventKey(virDomainPtr domain, const char *key)
+{
+ struct qemud_driver *driver = domain->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv;
+
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(domain->uuid, uuidstr);
+ qemuReportError(VIR_ERR_NO_DOMAIN,
+ _("no domain with matching uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
+ goto cleanup;
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorSendEventKey(priv->mon, key);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ if (qemuDomainObjEndJob(vm) == 0) {
+ vm = NULL;
+ goto cleanup;
+ }
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
static int qemudDomainGetInfo(virDomainPtr dom,
virDomainInfoPtr info) {
struct qemud_driver *driver = dom->conn->privateData;
@@ -6923,6 +7007,8 @@ static virDriver qemuDriver = {
qemuDomainSnapshotDelete, /* domainSnapshotDelete */
qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
qemuDomainOpenConsole, /* domainOpenConsole */
+ qemuDomainSendEventNMI, /* domainSendEventNMI */
+ qemuDomainSendEventKey, /* domainSendEventKey */
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2d28f8d..bc2e269 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2228,3 +2228,30 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply);
return ret;
}
+
+
+int qemuMonitorSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu)
+{
+ int ret;
+
+ VIR_DEBUG("mon=%p, vcpu=%u", mon, vcpu);
+
+ if (mon->json)
+ ret = qemuMonitorJSONSendEventNMI(mon, vcpu);
+ else
+ ret = qemuMonitorTextSendEventNMI(mon, vcpu);
+ return ret;
+}
+
+int qemuMonitorSendEventKey(qemuMonitorPtr mon, const char *key)
+{
+ int ret;
+
+ VIR_DEBUG("mon=%p, key sequence=%s", mon, key);
+
+ if (mon->json)
+ ret = qemuMonitorJSONSendEventKey(mon, key);
+ else
+ ret = qemuMonitorTextSendEventKey(mon, key);
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c90219b..fdc9859 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -423,6 +423,9 @@ int qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
char **reply,
bool hmp);
+int qemuMonitorSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu);
+int qemuMonitorSendEventKey(qemuMonitorPtr mon, const char *key);
+
/**
* When running two dd process and using <> redirection, we need a
* shell that will not truncate files. These two strings serve that
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 20a78e1..5149d9e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2513,3 +2513,71 @@ cleanup:
return ret;
}
+
+int qemuMonitorJSONSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu)
+{
+ int ret = -1;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+ char *hmp_cmd;
+
+ /*
+ * FIXME: qmp nmi is not supported until qemu-0.16.0,
+ * use human-monitor-command instead temporary.
+ */
+ if (virAsprintf(&hmp_cmd, "nmi %u", vcpu) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ cmd = qemuMonitorJSONMakeCommand("human-monitor-command",
+ "s:command-line", hmp_cmd,
+ NULL);
+ if (!cmd)
+ goto out_free_hmp_cmd;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+out_free_hmp_cmd:
+ VIR_FREE(hmp_cmd);
+ return ret;
+}
+
+int qemuMonitorJSONSendEventKey(qemuMonitorPtr mon, const char *key_seq)
+{
+ int ret = -1;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+ char *hmp_cmd;
+
+ /*
+ * FIXME: qmp sendkey is not supported until qemu-0.16.0,
+ * use human-monitor-command instead temporary.
+ */
+ if (virAsprintf(&hmp_cmd, "sendkey %s", key_seq) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ cmd = qemuMonitorJSONMakeCommand("human-monitor-command",
+ "s:command-line", hmp_cmd,
+ NULL);
+ if (!cmd)
+ goto out_free_hmp_cmd;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+out_free_hmp_cmd:
+ VIR_FREE(hmp_cmd);
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 086f0e1..dc206df 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -204,4 +204,7 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
char **reply_str,
bool hmp);
+int qemuMonitorJSONSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu);
+int qemuMonitorJSONSendEventKey(qemuMonitorPtr mon, const char *key);
+
#endif /* QEMU_MONITOR_JSON_H */
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index e0e3292..d3416a8 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -2627,3 +2627,59 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
return ret;
}
+
+int qemuMonitorTextSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu)
+{
+ char *cmd;
+ char *reply = NULL;
+ int ret = -1;
+
+ if (virAsprintf(&cmd, "nmi %u", vcpu) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ if (qemuMonitorTextArbitraryCommand(mon, cmd, &reply)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to send NMI using command '%s'"),
+ cmd);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(reply);
+ return ret;
+}
+
+int qemuMonitorTextSendEventKey(qemuMonitorPtr mon, const char *key)
+{
+ char *cmd;
+ char *reply = NULL;
+ int ret = -1;
+
+ if (virAsprintf(&cmd, "sendkey %s", key) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ if (qemuMonitorTextArbitraryCommand(mon, cmd, &reply)) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to send key using command '%s'"),
+ cmd);
+ goto cleanup;
+ }
+
+ if (strstr(reply, "unknown key") != NULL) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("sent unknown key"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(reply);
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 0838a2b..4a03c40 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -198,4 +198,6 @@ int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name);
int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
char **reply);
+int qemuMonitorTextSendEventNMI(qemuMonitorPtr mon, unsigned int vcpu);
+int qemuMonitorTextSendEventKey(qemuMonitorPtr mon, const char *key);
#endif /* QEMU_MONITOR_TEXT_H */
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index bf94e70..676f473 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -2929,6 +2929,54 @@ done:
}
static int
+remoteDomainSendEventNMI(virDomainPtr domain, unsigned int vcpu)
+{
+ int rv = -1;
+ remote_domain_send_event_nmi_args args;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.dom, domain);
+ args.vcpu = vcpu;
+
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SEND_EVENT_NMI,
+ (xdrproc_t) xdr_remote_domain_send_event_nmi_args, (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+static int
+remoteDomainSendEventKey(virDomainPtr domain, const char *key)
+{
+ int rv = -1;
+ remote_domain_send_event_key_args args;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.dom, domain);
+ args.key = (char *)key;
+
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SEND_EVENT_KEY,
+ (xdrproc_t) xdr_remote_domain_send_event_key_args, (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+static int
remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus)
{
int rv = -1;
@@ -11296,6 +11344,8 @@ static virDriver remote_driver = {
remoteDomainSnapshotDelete, /* domainSnapshotDelete */
remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
remoteDomainOpenConsole, /* domainOpenConsole */
+ remoteDomainSendEventNMI, /* domainSendEventNMI */
+ remoteDomainSendEventKey, /* domainSendEventKey */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index 5604371..a829219 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -1463,6 +1463,28 @@ xdr_remote_domain_undefine_args (XDR *xdrs, remote_domain_undefine_args *objp)
}
bool_t
+xdr_remote_domain_send_event_nmi_args (XDR *xdrs, remote_domain_send_event_nmi_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->vcpu))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_send_event_key_args (XDR *xdrs, remote_domain_send_event_key_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->key))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp)
{
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index d9bf151..027ef88 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -2200,6 +2200,19 @@ struct remote_storage_vol_download_args {
u_int flags;
};
typedef struct remote_storage_vol_download_args remote_storage_vol_download_args;
+
+struct remote_domain_send_event_nmi_args {
+ remote_nonnull_domain dom;
+ u_int vcpu;
+};
+typedef struct remote_domain_send_event_nmi_args remote_domain_send_event_nmi_args;
+
+struct remote_domain_send_event_key_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string key;
+};
+typedef struct remote_domain_send_event_key_args remote_domain_send_event_key_args;
+
#define REMOTE_PROGRAM 0x20008086
#define REMOTE_PROTOCOL_VERSION 1
@@ -2413,6 +2426,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207,
REMOTE_PROC_STORAGE_VOL_UPLOAD = 208,
REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209,
+ REMOTE_PROC_DOMAIN_SEND_EVENT_NMI = 210,
+ REMOTE_PROC_DOMAIN_SEND_EVENT_KEY = 211,
};
typedef enum remote_procedure remote_procedure;
@@ -2561,6 +2576,8 @@ extern bool_t xdr_remote_domain_create_with_flags_ret (XDR *, remote_domain_cre
extern bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xml_args*);
extern bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*);
extern bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*);
+extern bool_t xdr_remote_domain_send_event_nmi_args (XDR *, remote_domain_send_event_nmi_args*);
+extern bool_t xdr_remote_domain_send_event_key_args (XDR *, remote_domain_send_event_key_args*);
extern bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*);
extern bool_t xdr_remote_domain_set_vcpus_flags_args (XDR *, remote_domain_set_vcpus_flags_args*);
extern bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*);
@@ -2918,6 +2935,8 @@ extern bool_t xdr_remote_domain_create_with_flags_ret ();
extern bool_t xdr_remote_domain_define_xml_args ();
extern bool_t xdr_remote_domain_define_xml_ret ();
extern bool_t xdr_remote_domain_undefine_args ();
+extern bool_t xdr_remote_domain_send_event_nmi_args ();
+extern bool_t xdr_remote_domain_send_event_key_args ();
extern bool_t xdr_remote_domain_set_vcpus_args ();
extern bool_t xdr_remote_domain_set_vcpus_flags_args ();
extern bool_t xdr_remote_domain_get_vcpus_flags_args ();
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 675eccd..34600d7 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -817,6 +817,16 @@ struct remote_domain_undefine_args {
remote_nonnull_domain dom;
};
+struct remote_domain_send_event_nmi_args {
+ remote_nonnull_domain dom;
+ unsigned int vcpu;
+};
+
+struct remote_domain_send_event_key_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string key;
+};
+
struct remote_domain_set_vcpus_args {
remote_nonnull_domain dom;
int nvcpus;
@@ -2176,8 +2186,10 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206,
REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207,
REMOTE_PROC_STORAGE_VOL_UPLOAD = 208,
- REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209
+ REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209,
+ REMOTE_PROC_DOMAIN_SEND_EVENT_NMI = 210,
+ REMOTE_PROC_DOMAIN_SEND_EVENT_KEY = 211,
/*
* Notice how the entries are grouped in sets of 10 ?
* Nice isn't it. Please keep it this way when adding more.
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 17f5ad9..2163850 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -5447,6 +5447,8 @@ static virDriver testDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
static virNetworkDriver testNetworkDriver = {
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index e2bd5f2..756877d 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -2249,6 +2249,8 @@ static virDriver umlDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
umlDomainOpenConsole, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
static int
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 8bd27dd..73c5c87 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -8647,6 +8647,8 @@ virDriver NAME(Driver) = {
vboxDomainSnapshotDelete, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
virNetworkDriver NAME(NetworkDriver) = {
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
index b5e416b..eb64087 100644
--- a/src/vmware/vmware_driver.c
+++ b/src/vmware/vmware_driver.c
@@ -1007,6 +1007,8 @@ static virDriver vmwareDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
int
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 9f47722..bd82001 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -2141,6 +2141,8 @@ static virDriver xenUnifiedDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
xenUnifiedDomainOpenConsole, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
/**
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 27206a0..0f85ad8 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -1885,6 +1885,8 @@ static virDriver xenapiDriver = {
NULL, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainOpenConsole */
+ NULL, /* domainSendEventNMI */
+ NULL, /* domainSendEventKey */
};
/**
diff --git a/tools/virsh.c b/tools/virsh.c
index faeaf47..0b78c6d 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2910,6 +2910,61 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
}
/*
+ * "sendevent" command
+ */
+static const vshCmdInfo info_sendevent[] = {
+ {"help", N_("send events to the guest")},
+ {"desc", N_("Send events (NMI or Keys) to the guest domain.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_sendevent[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+ {"eventtype", VSH_OT_DATA, VSH_OFLAG_REQ, N_("the type of event (nmi or key)")},
+ {"eventcontent", VSH_OT_DATA, VSH_OFLAG_REQ, N_("content for the event.")},
+ {NULL, 0, 0, NULL}
+};
+
+
+static int
+cmdSendEvent(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ const char *type;
+ int ret = TRUE;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return FALSE;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ return FALSE;
+
+ if (vshCommandOptString(cmd, "eventtype", &type) < 0)
+ return FALSE;
+
+ if (STREQ(type, "nmi")) {
+ int cpu;
+
+ if ((vshCommandOptInt(cmd, "eventcontent", &cpu) < 0)
+ || (virDomainSendEventNMI(dom, cpu) < 0))
+ ret = FALSE;
+ } else if (STREQ(type, "key")) {
+ const char *key;
+
+ if ((vshCommandOptString(cmd, "eventcontent", &key) < 0)
+ || (virDomainSendEventKey(dom, key) < 0))
+ ret = FALSE;
+ } else {
+ virDomainFree(dom);
+ vshError(ctl, _("Invalid event type: %s, only \"nmi\" or \"key\" supported currently."), type);
+ return FALSE;
+ }
+
+ virDomainFree(dom);
+ return ret;
+}
+
+/*
* "setmemory" command
*/
static const vshCmdInfo info_setmem[] = {
@@ -10693,6 +10748,7 @@ static const vshCmdDef domManagementCmds[] = {
{"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
{"setmem", cmdSetmem, opts_setmem, info_setmem},
{"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
+ {"sendevent", cmdSendEvent, opts_sendevent, info_sendevent},
{"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
{"start", cmdStart, opts_start, info_start},
{"suspend", cmdSuspend, opts_suspend, info_suspend},
13 years, 7 months
[libvirt] [PATCH] Fix parted sector size assumption
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Parted does not report disk size in 512 byte units, but
rather the disks' logical sector size, which with modern
drives might be 4k.
* src/storage/parthelper.c: Remove hardcoded 512 byte sector
size
---
src/storage/parthelper.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/storage/parthelper.c b/src/storage/parthelper.c
index acc9171..964aa78 100644
--- a/src/storage/parthelper.c
+++ b/src/storage/parthelper.c
@@ -157,17 +157,17 @@ int main(int argc, char **argv)
part->num, '\0',
type, '\0',
content, '\0',
- part->geom.start * 512llu, '\0',
- (part->geom.end + 1 ) * 512llu, '\0',
- part->geom.length * 512llu, '\0');
+ part->geom.start * dev->sector_size, '\0',
+ (part->geom.end + 1 ) * dev->sector_size, '\0',
+ part->geom.length * dev->sector_size, '\0');
} else {
printf("%s%c%s%c%s%c%llu%c%llu%c%llu%c",
"-", '\0',
type, '\0',
content, '\0',
- part->geom.start * 512llu, '\0',
- (part->geom.end + 1 ) * 512llu, '\0',
- part->geom.length * 512llu, '\0');
+ part->geom.start * dev->sector_size, '\0',
+ (part->geom.end + 1 ) * dev->sector_size, '\0',
+ part->geom.length * dev->sector_size, '\0');
}
part = ped_disk_next_partition(disk, part);
}
--
1.7.6
13 years, 7 months
Re: [libvirt] The design choice for how to enable block I/O throttling function in libvirt
by Stefan Hajnoczi
On Tue, Aug 30, 2011 at 2:46 PM, Adam Litke <agl(a)us.ibm.com> wrote:
> On Tue, Aug 30, 2011 at 09:53:33AM +0100, Stefan Hajnoczi wrote:
>> On Tue, Aug 30, 2011 at 3:55 AM, Zhi Yong Wu <zwu.kernel(a)gmail.com> wrote:
>> > I am trying to enable block I/O throttling function in libvirt. But
>> > currently i met some design questions, and don't make sure if we
>> > should extend blkiotune to support block I/O throttling or introduce
>> > one new libvirt command "blkiothrottle" to cover it or not. If you
>> > have some better idea, pls don't hesitate to drop your comments.
>>
>> A little bit of context: this discussion is about adding libvirt
>> support for QEMU disk I/O throttling.
>
> Thanks for the additional context Stefan.
>
>> Today libvirt supports the cgroups blkio-controller, which handles
>> proportional shares and throughput/iops limits on host block devices.
>> blkio-controller does not support network file systems (NFS) or other
>> QEMU remote block drivers (curl, Ceph/rbd, sheepdog) since they are
>> not host block devices. QEMU I/O throttling works with all types of
>> -drive and therefore complements blkio-controller.
>
> The first question that pops into my mind is: Should a user need to understand
> when to use the cgroups blkio-controller vs. the QEMU I/O throttling method? In
> my opinion, it would be nice if libvirt had a single interface for block I/O
> throttling and libvirt would decide which mechanism to use based on the type of
> device and the specific limits that need to be set.
Yes, I agree it would be simplest to pick the right mechanism,
depending on the type of throttling the user wants. More below.
>> I/O throttling can be applied independently to each -drive attached to
>> a guest and supports throughput/iops limits. For more information on
>> this QEMU feature and a comparison with blkio-controller, see Ryan
>> Harper's KVM Forum 2011 presentation:
>
>> http://www.linux-kvm.org/wiki/images/7/72/2011-forum-keep-a-limit-on-it-i...
>
> From the presentation, it seems that both the cgroups method the the qemu method
> offer comparable control (assuming a block device) so it might possible to apply
> either method from the same API in a transparent manner. Am I correct or are we
> suggesting that the Qemu throttling approach should always be used for Qemu
> domains?
QEMU I/O throttling does not provide a proportional share mechanism.
So you cannot assign weights to VMs and let them receive a fraction of
the available disk time. That is only supported by cgroups
blkio-controller because it requires a global view which QEMU does not
have.
So I think the two are complementary:
If proportional share should be used on a host block device, use
cgroups blkio-controller.
Otherwise use QEMU I/O throttling.
Stefan
13 years, 7 months
[libvirt] [test-API][PATCH] Fix a typo which block windows cdrom install
by Wayne Sun
---
repos/domain/install_windows_cdrom.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/repos/domain/install_windows_cdrom.py b/repos/domain/install_windows_cdrom.py
index 9cf9e3b..b8333e2 100644
--- a/repos/domain/install_windows_cdrom.py
+++ b/repos/domain/install_windows_cdrom.py
@@ -296,7 +296,7 @@ def install_windows_cdrom(params):
logger.debug("the uri to connect is %s" % uri)
if params.has_key('imagepath') and not params.has_key('volumepath'):
- imgfullpath = os..path.join(params.get('imagepath'), guestname)
+ imgfullpath = os.path.join(params.get('imagepath'), guestname)
elif not params.has_key('imagepath') and not params.has_key('volumepath'):
if hypervisor == 'xen':
imgfullpath = os.path.join('/var/lib/xen/images', guestname)
--
1.7.1
13 years, 7 months
[libvirt] [test-API][PATCH v3] Add ownership_test.py test case
by Wayne Sun
* Save a domain to a file which chown is qemu:qemu, check the ownership
of the file after save and restore operation. With use_nfs enable or
not, the saved file could be on local or mounted root_squash nfs dir.
---
repos/domain/ownership_test.py | 315 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 315 insertions(+), 0 deletions(-)
create mode 100644 repos/domain/ownership_test.py
diff --git a/repos/domain/ownership_test.py b/repos/domain/ownership_test.py
new file mode 100644
index 0000000..1957428
--- /dev/null
+++ b/repos/domain/ownership_test.py
@@ -0,0 +1,315 @@
+#!/usr/bin/env python
+"""Setting the dynamic_ownership in /etc/libvirt/qemu.conf,
+ check the ownership of saved domain file. Test could be on
+ local or root_squash nfs. The default owner of the saved
+ domain file is qemu:qemu in this case.
+ domain:ownership_test
+ guestname
+ #GUESTNAME#
+ dynamic_ownership
+ 0|1
+ use_nfs
+ enable|disable
+
+ use_nfs is a flag for decide using root_squash nfs or not
+"""
+
+__author__ = 'Wayne Sun: gsun(a)redhat.com'
+__date__ = 'Mon Jul 25, 2011'
+__version__ = '0.1.0'
+__credits__ = 'Copyright (C) 2011 Red Hat, Inc.'
+__all__ = ['ownership_test']
+
+import os
+import re
+import sys
+import commands
+
+QEMU_CONF = "/etc/libvirt/qemu.conf"
+SAVE_FILE = "/mnt/test.save"
+TEMP_FILE = "/tmp/test.save"
+
+from utils.Python import utils
+
+def append_path(path):
+ """Append root path of package"""
+ if path in sys.path:
+ pass
+ else:
+ sys.path.append(path)
+
+from lib import connectAPI
+from lib import domainAPI
+from utils.Python import utils
+from exception import LibvirtAPI
+
+pwd = os.getcwd()
+result = re.search('(.*)libvirt-test-API', pwd)
+append_path(result.group(0))
+
+def return_close(conn, logger, ret):
+ conn.close()
+ logger.info("closed hypervisor connection")
+ return ret
+
+def check_params(params):
+ """Verify inputing parameter dictionary"""
+ logger = params['logger']
+ keys = ['guestname', 'dynamic_ownership', 'use_nfs']
+ for key in keys:
+ if key not in params:
+ logger.error("%s is required" %key)
+ return 1
+ return 0
+
+def nfs_setup(util, logger):
+ """setup nfs on localhost
+ """
+ logger.info("set nfs service")
+ cmd = "echo /tmp *\(rw,root_squash\) > /etc/exports"
+ ret, out = util.exec_cmd(cmd, shell=True)
+ if ret:
+ logger.error("failed to config nfs export")
+ return 1
+
+ logger.info("start nfs service")
+ cmd = "service nfs start"
+ ret, out = util.exec_cmd(cmd, shell=True)
+ if ret:
+ logger.error("failed to start nfs service")
+ return 1
+ else:
+ for i in range(len(out)):
+ logger.info(out[i])
+
+ return 0
+
+def chown_file(util, filepath, logger):
+ """touch a file and setting the chown
+ """
+ if os.path.exists(filepath):
+ os.remove(filepath)
+
+ touch_cmd = "touch %s" % filepath
+ logger.info(touch_cmd)
+ ret, out = util.exec_cmd(touch_cmd, shell=True)
+ if ret:
+ logger.error("failed to touch a new file")
+ logger.error(out[0])
+ return 1
+
+ logger.info("set chown of %s as 107:107" % filepath)
+ chown_cmd = "chown 107:107 %s" % filepath
+ ret, out = util.exec_cmd(chown_cmd, shell=True)
+ if ret:
+ logger.error("failed to set the ownership of %s" % filepath)
+ return 1
+
+ logger.info("set %s mode as 664" % filepath)
+ cmd = "chmod 664 %s" % filepath
+ ret, out = util.exec_cmd(cmd, shell=True)
+ if ret:
+ logger.error("failed to set the mode of %s" % filepath)
+ return 1
+
+ return 0
+
+def prepare_env(util, guestname, dynamic_ownership, use_nfs, logger):
+ """configure dynamic_ownership in /etc/libvirt/qemu.conf,
+ set chown of the file to save
+ """
+ logger.info("set the dynamic ownership in %s as %s" % \
+ (QEMU_CONF, dynamic_ownership))
+ set_cmd = "echo dynamic_ownership = %s >> %s" % (dynamic_ownership, QEMU_CONF)
+ ret, out = util.exec_cmd(set_cmd, shell=True)
+ if ret:
+ logger.error("failed to set dynamic ownership")
+ return 1
+
+ logger.info("restart libvirtd")
+ restart_cmd = "service libvirtd restart"
+ ret, out = util.exec_cmd(restart_cmd, shell=True)
+ if ret:
+ logger.error("failed to restart libvirtd")
+ return 1
+ else:
+ for i in range(len(out)):
+ logger.info(out[i])
+
+ if use_nfs == 'enable':
+ filepath = TEMP_FILE
+ elif use_nfs == 'disable':
+ filepath = SAVE_FILE
+
+ ret = chown_file(util, filepath, logger)
+ if ret:
+ return 1
+
+ if use_nfs == 'enable':
+ ret = nfs_setup(util, logger)
+ if ret:
+ return 1
+
+ cmd = "setsebool virt_use_nfs 1"
+ logger.info(cmd)
+ ret, out = util.exec_cmd(cmd, shell=True)
+ if ret:
+ logger.error("Failed to setsebool virt_use_nfs")
+ return 1
+
+ logger.info("mount the nfs path to /mnt")
+ mount_cmd = "mount -o vers=3 127.0.0.1:/tmp /mnt"
+ ret, out = util.exec_cmd(mount_cmd, shell=True)
+ if ret:
+ logger.error("Failed to mount the nfs path")
+ for i in range(len(out)):
+ logger.info(out[i])
+ return 1
+
+ return 0
+
+def ownership_get(logger):
+ """check the ownership of file"""
+
+ statinfo = os.stat(SAVE_FILE)
+ uid = statinfo.st_uid
+ gid = statinfo.st_gid
+
+ logger.info("the uid and gid of %s is %s:%s" %(SAVE_FILE, uid, gid))
+
+ return 0, uid, gid
+
+def ownership_test(params):
+ """Save a domain to a file, check the ownership of
+ the file after save and restore
+ """
+ # Initiate and check parameters
+ params_check_result = check_params(params)
+ if params_check_result:
+ return 1
+
+ logger = params['logger']
+ guestname = params['guestname']
+ dynamic_ownership = params['dynamic_ownership']
+ use_nfs = params['use_nfs']
+ test_result = False
+
+ util = utils.Utils()
+
+ # set env
+ logger.info("prepare the environment")
+ ret = prepare_env(util, guestname, dynamic_ownership, use_nfs, logger)
+ if ret:
+ logger.error("failed to prepare the environment")
+ return 1
+
+ # Connect to local hypervisor connection URI
+ uri = util.get_uri('127.0.0.1')
+ conn = connectAPI.ConnectAPI()
+ virconn = conn.open(uri)
+
+ # save domain to the file
+ logger.info("save the domain to the file")
+ domobj = domainAPI.DomainAPI(virconn)
+ try:
+ domobj.save(guestname, SAVE_FILE)
+ logger.info("Success save domain to file")
+ except LibvirtAPI, e:
+ logger.error("API error message: %s, error code is %s" % \
+ (e.response()['message'], e.response()['code']))
+ logger.error("Error: fail to save %s domain" %guestname)
+ return return_close(conn, logger, 1)
+
+ logger.info("check the ownership of %s after save" % SAVE_FILE)
+ ret, uid, gid = ownership_get(logger)
+ if use_nfs == 'enable':
+ if uid == 107 and gid == 107:
+ logger.info("As expected, the chown not change.")
+ test_result = True
+ else:
+ logger.error("The chown of %s is %s:%s, it's not as expected" % \
+ (SAVE_FILE, uid, gid))
+ return return_close(conn, logger, 1)
+ elif use_nfs == 'disable':
+ if dynamic_ownership == '1':
+ if uid == 0 and gid == 0:
+ logger.info("As expected, the chown changed to root:root")
+ test_result = True
+ else:
+ logger.error("The chown of %s is %s:%s, it's not as expected" % \
+ (SAVE_FILE, uid, gid))
+ return return_close(conn, logger, 1)
+ elif dynamic_ownership == '0':
+ if uid == 107 and gid == 107:
+ logger.info("As expected, the chown not change.")
+ test_result = True
+ else:
+ logger.error("The chown of %s is %s:%s, it's not as expected" % \
+ (SAVE_FILE, uid, gid))
+ return return_close(conn, logger, 1)
+ else:
+ logger.error("wrong dynamic_ownership value %s" % dynamic_ownership)
+ return return_close(conn, logger, 1)
+
+
+ # restore domain from file
+ logger.info("restore the domain from the file")
+ try:
+ domobj.restore(guestname, SAVE_FILE)
+ logger.info("check the ownership of %s after restore" % SAVE_FILE)
+ ret, uid, gid = ownership_get(logger)
+ if uid == 107 and gid == 107:
+ logger.info("As expected, the chown not change.")
+ test_result = True
+ else:
+ logger.error("The chown of %s is %s:%s, not change back as expected" % \
+ (SAVE_FILE, uid, gid))
+ test_result = False
+ except LibvirtAPI, e:
+ logger.error("API error message: %s, error code is %s" % \
+ (e.response()['message'], e.response()['code']))
+ logger.error("Error: fail to restore %s domain" %guestname)
+ test_result = False
+
+ if test_result:
+ return return_close(conn, logger, 0)
+ else:
+ return return_close(conn, logger, 1)
+
+def ownership_test_clean(params):
+ """clean testing environment"""
+ logger = params['logger']
+ use_nfs = params['use_nfs']
+
+ util = utils.Utils()
+
+ if use_nfs == 'enable':
+ logger.info("umount the nfs path")
+ umount_cmd = "umount /mnt"
+ ret, out = util.exec_cmd(umount_cmd, shell=True)
+ if ret:
+ logger.error("Failed to mount the nfs path")
+ for i in range(len(out)):
+ logger.error(out[i])
+
+ logger.info("stop nfs service")
+ cmd = "service nfs stop"
+ ret, out = util.exec_cmd(cmd, shell=True)
+ if ret:
+ logger.error("Failed to stop nfs service")
+ for i in range(len(out)):
+ logger.error(out[i])
+
+ logger.info("clear the exports file")
+ cmd = ">/etc/exports"
+ if ret:
+ logger.error("Failed to clear exports file")
+
+ filepath = TEMP_FILE
+ elif use_nfs == 'disable':
+ filepath = SAVE_FILE
+
+ if os.path.exists(filepath):
+ logger.info("remove dump file from save %s" % filepath)
+ os.remove(filepath)
+
--
1.7.1
13 years, 7 months
[libvirt] [test-API][PATCH 1/3] Remove API wrappers that have been flagged internal use
by Guannan Ren
*lib/connectAPI.py
---
lib/connectAPI.py | 108 -----------------------------------------------------
1 files changed, 0 insertions(+), 108 deletions(-)
diff --git a/lib/connectAPI.py b/lib/connectAPI.py
index cfa4fea..9f2b728 100644
--- a/lib/connectAPI.py
+++ b/lib/connectAPI.py
@@ -248,114 +248,6 @@ class ConnectAPI(object):
code = e.get_error_code()
raise exception.LibvirtAPI(message, code)
- def dispatch_domain_event_callback(self, dom, event, detail):
- try:
- return self.conn.dispatchDomainEventCallbacks(dom, event, detail)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_generic_callback(self, dom, cbData):
- try:
- return self.conn.dispatchDomainEventGenericCallback(dom, cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_graphics_callback(self,
- dom,
- phase,
- localAddr,
- remoteAddr,
- authScheme,
- subject,
- cbData):
- try:
- return self.conn.dispatchDomainEventGraphicsCallback(dom,
- phase,
- localAddr,
- remoteAddr,
- authScheme,
- subject,
- cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_IOError_callback(self,
- dom,
- srcPath,
- devAlias,
- action,
- cbData):
- try:
- return self.conn.dispatchDomainEventIOErrorCallback(dom,
- srcPath,
- devAlias,
- action,
- cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_IOError_reason_callback(self,
- dom,
- srcPath,
- devAlias,
- action,
- reason,
- cbData):
- try:
- return self.conn.dispatchDomainEventIOErrorReasonCallback(dom,
- srcPath,
- devAlias,
- action,
- reason,
- cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_lifecycle_callback(self,
- dom,
- event,
- detail,
- cbData):
- try:
- return self.conn.dispatchDomainEventLifecycleCallback(dom,
- event,
- detail,
- cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_RTC_change_callback(self, dom, offset, cbData):
- try:
- return self.conn.dispatchDomainEventRTCChangeCallback(dom,
- offset,
- cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
- def dispatch_domain_event_watchdog_callback(self, dom, action, cbData):
- try:
- return self.conn.dispatchDomainEventWatchdogCallback(dom,
- action,
- cbData)
- except libvirt.libvirtError, e:
- message = e.get_error_message()
- code = e.get_error_code()
- raise exception.LibvirtAPI(message, code)
-
def domain_event_deregister(self, cb):
try:
return self.conn.domainEventDeregister(cb)
--
1.7.1
13 years, 7 months
[libvirt] [PATCH] Remove bogus virSecurityManagerSetProcessFDLabel method
by Daniel P. Berrange
The virSecurityManagerSetProcessFDLabel method was introduced
after a mis-understanding from a conversation about SELinux
socket labelling. The virSecurityManagerSetSocketLabel method
should have been used for all such scenarios.
* src/security/security_apparmor.c, src/security/security_apparmor.c,
src/security/security_driver.h, src/security/security_manager.c,
src/security/security_manager.h, src/security/security_selinux.c,
src/security/security_stack.c: Remove SetProcessFDLabel driver
---
src/security/security_apparmor.c | 29 -----------------------------
src/security/security_dac.c | 9 ---------
src/security/security_driver.h | 4 ----
src/security/security_manager.c | 11 -----------
src/security/security_manager.h | 3 ---
src/security/security_selinux.c | 14 --------------
src/security/security_stack.c | 18 ------------------
7 files changed, 0 insertions(+), 88 deletions(-)
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index dbd1290..299dcc6 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -799,34 +799,6 @@ AppArmorSetImageFDLabel(virSecurityManagerPtr mgr,
return reload_profile(mgr, vm, fd_path, true);
}
-static int
-AppArmorSetProcessFDLabel(virSecurityManagerPtr mgr,
- virDomainObjPtr vm,
- int fd)
-{
- int rc = -1;
- char *proc = NULL;
- char *fd_path = NULL;
-
- const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
-
- if (secdef->imagelabel == NULL)
- return 0;
-
- if (virAsprintf(&proc, "/proc/self/fd/%d", fd) == -1) {
- virReportOOMError();
- return rc;
- }
-
- if (virFileResolveLink(proc, &fd_path) < 0) {
- virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("could not find path for descriptor"));
- return rc;
- }
-
- return reload_profile(mgr, vm, fd_path, true);
-}
-
virSecurityDriver virAppArmorSecurityDriver = {
0,
SECURITY_APPARMOR_NAME,
@@ -863,5 +835,4 @@ virSecurityDriver virAppArmorSecurityDriver = {
AppArmorRestoreSavedStateLabel,
AppArmorSetImageFDLabel,
- AppArmorSetProcessFDLabel,
};
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index e5465fc..af02236 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -697,14 +697,6 @@ virSecurityDACSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
return 0;
}
-static int
-virSecurityDACSetProcessFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
- virDomainObjPtr vm ATTRIBUTE_UNUSED,
- int fd ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
virSecurityDriver virSecurityDriverDAC = {
sizeof(virSecurityDACData),
@@ -743,5 +735,4 @@ virSecurityDriver virSecurityDriverDAC = {
virSecurityDACRestoreSavedStateLabel,
virSecurityDACSetImageFDLabel,
- virSecurityDACSetProcessFDLabel,
};
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index 94f27f8..aea90b0 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -84,9 +84,6 @@ typedef int (*virSecurityDomainSecurityVerify) (virSecurityManagerPtr mgr,
typedef int (*virSecurityDomainSetImageFDLabel) (virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int fd);
-typedef int (*virSecurityDomainSetProcessFDLabel) (virSecurityManagerPtr mgr,
- virDomainObjPtr vm,
- int fd);
struct _virSecurityDriver {
size_t privateDataLen;
@@ -124,7 +121,6 @@ struct _virSecurityDriver {
virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
virSecurityDomainSetImageFDLabel domainSetSecurityImageFDLabel;
- virSecurityDomainSetProcessFDLabel domainSetSecurityProcessFDLabel;
};
virSecurityDriverPtr virSecurityDriverLookup(const char *name);
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index b2fd0d0..cae9b83 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -346,14 +346,3 @@ int virSecurityManagerSetImageFDLabel(virSecurityManagerPtr mgr,
virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
-
-int virSecurityManagerSetProcessFDLabel(virSecurityManagerPtr mgr,
- virDomainObjPtr vm,
- int fd)
-{
- if (mgr->drv->domainSetSecurityProcessFDLabel)
- return mgr->drv->domainSetSecurityProcessFDLabel(mgr, vm, fd);
-
- virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
- return -1;
-}
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index 38342c2..12cd498 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -96,8 +96,5 @@ int virSecurityManagerVerify(virSecurityManagerPtr mgr,
int virSecurityManagerSetImageFDLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int fd);
-int virSecurityManagerSetProcessFDLabel(virSecurityManagerPtr mgr,
- virDomainObjPtr vm,
- int fd);
#endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index cddbed5..ca54f9b 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1321,19 +1321,6 @@ SELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
return SELinuxFSetFilecon(fd, secdef->imagelabel);
}
-static int
-SELinuxSetProcessFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
- virDomainObjPtr vm,
- int fd)
-{
- const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
-
- if (secdef->label == NULL)
- return 0;
-
- return SELinuxFSetFilecon(fd, secdef->label);
-}
-
virSecurityDriver virSecurityDriverSELinux = {
0,
SECURITY_SELINUX_NAME,
@@ -1370,5 +1357,4 @@ virSecurityDriver virSecurityDriverSELinux = {
SELinuxRestoreSavedStateLabel,
SELinuxSetImageFDLabel,
- SELinuxSetProcessFDLabel,
};
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
index f263f5b..3f601c1 100644
--- a/src/security/security_stack.c
+++ b/src/security/security_stack.c
@@ -402,23 +402,6 @@ virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
}
-static int
-virSecurityStackSetProcessFDLabel(virSecurityManagerPtr mgr,
- virDomainObjPtr vm,
- int fd)
-{
- virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
- int rc = 0;
-
- if (virSecurityManagerSetProcessFDLabel(priv->secondary, vm, fd) < 0)
- rc = -1;
- if (virSecurityManagerSetProcessFDLabel(priv->primary, vm, fd) < 0)
- rc = -1;
-
- return rc;
-}
-
-
virSecurityDriver virSecurityDriverStack = {
sizeof(virSecurityStackData),
"stack",
@@ -455,5 +438,4 @@ virSecurityDriver virSecurityDriverStack = {
virSecurityStackRestoreSavedStateLabel,
virSecurityStackSetImageFDLabel,
- virSecurityStackSetProcessFDLabel,
};
--
1.7.4.4
13 years, 7 months
[libvirt] [PATCH] snapshot: forbid snapshot on autodestroy domain
by Eric Blake
There is no reason to forbid pausing an autodestroy domain
(not to mention that 'virsh start --paused --autodestroy'
succeeds in creating a paused autodestroy domain).
Meanwhile, qemu was failing to enforce the API documentation that
autodestroy domains cannot be saved. And while the original
documentation only mentioned save/restore, snapshots are another
form of saving that are close enough in semantics as to make no
sense on one-shot domains.
* src/qemu/qemu_driver.c (qemudDomainSuspend): Drop bogus check.
(qemuDomainSaveInternal, qemuDomainSnapshotCreateXML): Forbid
saves of autodestroy domains.
* src/libvirt.c (virDomainCreateWithFlags, virDomainCreateXML):
Document snapshot interaction.
---
Sending this one separately for v1, but I'll insert it into the
front of my snapshot series (before 1/43) when I post v4 of that.
src/libvirt.c | 4 ++--
src/qemu/qemu_driver.c | 18 ++++++++++++------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index 65a099b..711580e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1822,7 +1822,7 @@ virDomainGetConnect (virDomainPtr dom)
* object is finally released. This will also happen if the
* client application crashes / loses its connection to the
* libvirtd daemon. Any domains marked for auto destroy will
- * block attempts at migration or save-to-file
+ * block attempts at migration, save-to-file, or snapshots.
*
* Returns a new domain object or NULL in case of failure
*/
@@ -7073,7 +7073,7 @@ error:
* object is finally released. This will also happen if the
* client application crashes / loses its connection to the
* libvirtd daemon. Any domains marked for auto destroy will
- * block attempts at migration or save-to-file
+ * block attempts at migration, save-to-file, or snapshots.
*
* If the VIR_DOMAIN_START_BYPASS_CACHE flag is set, and there is a
* managed save file for this domain (created by virDomainManagedSave()),
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f21122d..737eec8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1360,12 +1360,6 @@ static int qemudDomainSuspend(virDomainPtr dom) {
goto cleanup;
}
- if (qemuProcessAutoDestroyActive(driver, vm)) {
- qemuReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domain is marked for auto destroy"));
- goto cleanup;
- }
-
priv = vm->privateData;
if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) {
@@ -2225,6 +2219,12 @@ qemuDomainSaveInternal(struct qemud_driver *driver, virDomainPtr dom,
int directFlag = 0;
virFileDirectFdPtr directFd = NULL;
+ if (qemuProcessAutoDestroyActive(driver, vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is marked for auto destroy"));
+ return -1;
+ }
+
memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
header.version = QEMUD_SAVE_VERSION;
@@ -8471,6 +8471,12 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
goto cleanup;
}
+ if (qemuProcessAutoDestroyActive(driver, vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is marked for auto destroy"));
+ goto cleanup;
+ }
+
/* in a perfect world, we would allow qemu to tell us this. The problem
* is that qemu only does this check device-by-device; so if you had a
* domain that booted from a large qcow2 device, but had a secondary raw
--
1.7.4.4
13 years, 7 months
[libvirt] [PATCH] Fix sanlock socket security labelling
by Daniel P. Berrange
It is not possible to change the label of a TCP socket once it
has been opened. When creating a TCP socket care must be taken
to ensure the socket creation label is set & then cleared.
Remove the bogus call to virSecurityManagerSetProcessFDLabel
from the lock driver guest setup code and instead make use of
virSecurityManagerSetSocketLabel
---
src/qemu/qemu_process.c | 19 ++++++++++++-------
1 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 58b4d36..c22974f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2081,15 +2081,26 @@ static int qemuProcessHook(void *data)
h->vm->pid = getpid();
VIR_DEBUG("Obtaining domain lock");
+ /*
+ * Since we're going to leak the returned FD to QEMU,
+ * we need to make sure it gets a sensible label.
+ * This mildly sucks, because there could be other
+ * sockets the lock driver opens that we don't want
+ * labelled. So far we're ok though.
+ */
+ if (virSecurityManagerSetSocketLabel(h->driver->securityManager, h->vm) < 0)
+ goto cleanup;
if (virDomainLockProcessStart(h->driver->lockManager,
h->vm,
/* QEMU is always pased initially */
true,
&fd) < 0)
goto cleanup;
+ if (virSecurityManagerClearSocketLabel(h->driver->securityManager, h->vm) < 0)
+ goto cleanup;
if (qemuProcessLimits(h->driver) < 0)
- return -1;
+ goto cleanup;
/* This must take place before exec(), so that all QEMU
* memory allocation is on the correct NUMA node
@@ -2111,12 +2122,6 @@ static int qemuProcessHook(void *data)
if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm) < 0)
goto cleanup;
- if (fd != -1) {
- VIR_DEBUG("Setting up lock manager FD labelling");
- if (virSecurityManagerSetProcessFDLabel(h->driver->securityManager, h->vm, fd) < 0)
- goto cleanup;
- }
-
ret = 0;
cleanup:
--
1.7.4.4
13 years, 7 months
[libvirt] [PATCH] Fix incorrect path length check in sanlock lockspace setup
by Daniel P. Berrange
The code for creating a sanlock lockspace accidentally used
SANLK_NAME_LEN instead of SANLK_PATH_LEN for a size check.
This meant disk paths were limited to 48 bytes !
* src/locking/lock_driver_sanlock.c: Fix disk path length
check
---
src/locking/lock_driver_sanlock.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/locking/lock_driver_sanlock.c b/src/locking/lock_driver_sanlock.c
index b85f1fa..b93fe01 100644
--- a/src/locking/lock_driver_sanlock.c
+++ b/src/locking/lock_driver_sanlock.c
@@ -159,10 +159,10 @@ static int virLockManagerSanlockSetupLockspace(void)
memcpy(ls.name, VIR_LOCK_MANAGER_SANLOCK_AUTO_DISK_LOCKSPACE, SANLK_NAME_LEN);
ls.host_id = 0; /* Doesn't matter for initialization */
ls.flags = 0;
- if (!virStrcpy(ls.host_id_disk.path, path, SANLK_NAME_LEN)) {
+ if (!virStrcpy(ls.host_id_disk.path, path, SANLK_PATH_LEN)) {
virLockError(VIR_ERR_INTERNAL_ERROR,
_("Lockspace path '%s' exceeded %d characters"),
- path, SANLK_NAME_LEN);
+ path, SANLK_PATH_LEN);
goto error;
}
ls.host_id_disk.offset = 0;
--
1.7.4.4
13 years, 7 months