[libvirt] [PATCH v4 0/7] support guest agent general command
Hi. All. I rewrote the patched for git head tree, adding some code. And @timeout must be following VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK(-2) : does not block and wait forever. VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT(-1) : use default time for waiting VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWIAT(0) : does not wait and out soon positive value : wait for pointed seconds. And I also add VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN for not writing static value. In addition, I added the some options for virsh command qemu-agent-command --block : it means taht @timeout is VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK. --async : it means taht @timeout is VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWIAT. --timeout @seconds : @seconds must be positive value and it means that @timeout is positive value case. These upper options are exclusive. If no options are given, it means taht @timeout is IR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT. virsh # help qemu-agent-command NAME qemu-agent-command - QEMU Guest Agent Command SYNOPSIS qemu-agent-command domain [--timeout number] [--async] [--block] {[--cmd] string}... DESCRIPTION Run an arbitrary qemu guest agent command; use at your own risk OPTIONS [--domain] string domain name, id or uuid --timeout number timeout seconds. must be positive. --async execute command without waiting for timeout --block execute command without timeout [--cmd] string command virsh # qemu-agent-command RHEL58_64 '{execute:guest-info}' {return:{version:1.1.50,supported_commands:[{enabled:true,name:guest-network-get-interfaces},{enabled:true,name:guest-suspend-hybrid},{enabled:true,name:guest-suspend-ram},{enabled:true,name:guest-suspend-disk},{enabled:true,name:guest-fsfreeze-thaw},{enabled:true,name:guest-fsfreeze-freeze},{enabled:true,name:guest-fsfreeze-status},{enabled:true,name:guest-file-flush},{enabled:true,name:guest-file-seek},{enabled:true,name:guest-file-write},{enabled:true,name:guest-file-read},{enabled:true,name:guest-file-close},{enabled:true,name:guest-file-open},{enabled:true,name:guest-shutdown},{enabled:true,name:guest-info},{enabled:true,name:guest-ping},{enabled:true,name:guest-sync},{enabled:true,name:guest-sync-delimited}]}} virsh # qemu-agent-command --block RHEL58_64 '{execute:guest-sync,arguments:{id:123}}' {return:123} -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 5/7] add remote driver support Add qemuDomainAgentCommand() which is generated automatically, for .qemuDomainArbitraryAgentCommand to remote driver.
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- src/qemu_protocol-structs | 10 ++ src/remote/qemu_protocol.x | 14 +- src/remote/remote_driver.c |1 + 3 files changed, 24 insertions(+), 1 deletions(-) diff --git a/src/qemu_protocol-structs b/src/qemu_protocol-structs index 67968eb..e6cde60 100644 --- a/src/qemu_protocol-structs +++ b/src/qemu_protocol-structs @@ -19,7 +19,17 @@ struct qemu_domain_attach_args { struct qemu_domain_attach_ret { remote_nonnull_domain dom; }; +struct qemu_domain_agent_command_args { +remote_nonnull_domain dom; +remote_nonnull_string cmd; +inttimeout; +u_int flags; +}; +struct qemu_domain_agent_command_ret { +remote_string result; +}; enum qemu_procedure { QEMU_PROC_MONITOR_COMMAND = 1, QEMU_PROC_DOMAIN_ATTACH = 2, +QEMU_PROC_DOMAIN_AGENT_COMMAND = 3, }; diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x index c06339c..914caed 100644 --- a/src/remote/qemu_protocol.x +++ b/src/remote/qemu_protocol.x @@ -47,6 +47,17 @@ struct qemu_domain_attach_ret { remote_nonnull_domain dom; }; +struct qemu_domain_agent_command_args { +remote_nonnull_domain dom; +remote_nonnull_string cmd; +int timeout; +unsigned int flags; +}; + +struct qemu_domain_agent_command_ret { +remote_string result; +}; + /* Define the program number, protocol version and procedure numbers here. */ const QEMU_PROGRAM = 0x20008087; const QEMU_PROTOCOL_VERSION = 1; @@ -61,5 +72,6 @@ enum qemu_procedure { * are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY * be marked as high priority. If in doubt, it's safe to choose low. */ QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen priority:low */ -QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen priority:low */ +QEMU_PROC_DOMAIN_ATTACH = 2, /* autogen autogen priority:low */ +QEMU_PROC_DOMAIN_AGENT_COMMAND = 3 /* autogen autogen priority:low */ }; diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 977d139..aa234b3 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -5416,6 +5416,7 @@ static virDriver remote_driver = { .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */ .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */ .domainGetHostname = remoteDomainGetHostname, /* 0.10.0 */ +.qemuDomainArbitraryAgentCommand = qemuDomainAgentCommand, /* 0.10.1 */ }; static virNetworkDriver network_driver = { -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 3/7] Add virDrvDomainQemuAgentCommand prototype for drivers. Add virDrvDomainQemuAgentCommand prototype for drivers. Add virDomainQemuAgentCommand() for virDrvDomainQemuAgentComman
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- include/libvirt/libvirt-qemu.h |3 ++ python/generator.py|1 + src/driver.h |4 +++ src/libvirt-qemu.c | 54 src/libvirt_qemu.syms |5 +++ 5 files changed, 67 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index 93386ca..d7f8703 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -51,6 +51,9 @@ typedef enum { VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, } virDomainQemuAgentCommandTimeoutValues; +char *virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd, +int timeout, unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/python/generator.py b/python/generator.py index 1f87195..7beb361 100755 --- a/python/generator.py +++ b/python/generator.py @@ -431,6 +431,7 @@ skip_impl = ( qemu_skip_impl = ( 'virDomainQemuMonitorCommand', +'virDomainQemuAgentCommand', ) diff --git a/src/driver.h b/src/driver.h index 203497d..7ee103e 100644 --- a/src/driver.h +++ b/src/driver.h @@ -691,6 +691,9 @@ typedef int typedef int (*virDrvDomainQemuMonitorCommand)(virDomainPtr domain, const char *cmd, char **result, unsigned int flags); +typedef char * +(*virDrvDomainQemuAgentCommand)(virDomainPtr domain, const char *cmd, +int timeout, unsigned int flags); /* Choice of unsigned int rather than pid_t is intentional. */ typedef virDomainPtr @@ -1052,6 +1055,7 @@ struct _virDriver { virDrvDomainGetDiskErrors domainGetDiskErrors; virDrvDomainSetMetadata domainSetMetadata; virDrvDomainGetMetadata domainGetMetadata; +virDrvDomainQemuAgentCommandqemuDomainArbitraryAgentCommand; }; typedef int diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c index 78480bb..7a45242 100644 --- a/src/libvirt-qemu.c +++ b/src/libvirt-qemu.c @@ -185,3 +185,57 @@ error: virDispatchError(conn); return NULL; } + +/** + * virDomainQemuAgentCommand: + * @domain: a domain object + * @cmd: the guest agent command string + * @timeout: timeout seconds + * @flags: execution flags + * + * Execute an arbitrary Guest Agent command. + * + * Issue @cmd to the guest agent running in @domain. + * @timeout must be -2, -1, 0 or positive. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK(-2): meaning to block forever waiting for + * a result. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT(-1): use default timeout value. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT(0): does not wait. + * positive value: wait for @timeout seconds + * + * Returns strings if success, NULL in failure. + */ +char * +virDomainQemuAgentCommand(virDomainPtr domain, + const char *cmd, + int timeout, + unsigned int flags) +{ +virConnectPtr conn; + +VIR_DEBUG(domain=%p, cmd=%s, timeout=%d, flags=%x, + domain, cmd, timeout, flags); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return NULL; +} +if (domain-conn-flags VIR_CONNECT_RO) { +virLibDomainError(NULL, VIR_ERR_OPERATION_DENIED, __FUNCTION__); +return NULL; +} + +conn = domain-conn; + +if (conn-driver-qemuDomainArbitraryAgentCommand) { +return conn-driver-qemuDomainArbitraryAgentCommand(domain, cmd, + timeout, flags); +} + +virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +/* Copy to connection error object for back compatibility */ +virDispatchError(conn); +return NULL; +} diff --git a/src/libvirt_qemu.syms b/src/libvirt_qemu.syms index 8447730..6e11509 100644 --- a/src/libvirt_qemu.syms +++ b/src/libvirt_qemu.syms @@ -19,3 +19,8 @@ LIBVIRT_QEMU_0.9.4 { global: virDomainQemuAttach; } LIBVIRT_QEMU_0.8.3; + +LIBVIRT_QEMU_0.10.1 { +global: +virDomainQemuAgentCommand; +} LIBVIRT_QEMU_0.9.4; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 4/7] add qemu driver support Add qemuDrvDomainAgentCommand() for .qemuDomainArbitraryAgentCommand to qemu driver.
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- src/qemu/qemu_driver.c | 71 1 files changed, 71 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 109d18d..a62d1bb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -13437,6 +13437,76 @@ qemuListAllDomains(virConnectPtr conn, return ret; } +static char * +qemuDrvDomainAgentCommand(virDomainPtr domain, + const char *cmd, + int timeout, + unsigned int flags) +{ +struct qemud_driver *driver = domain-conn-privateData; +virDomainObjPtr vm; +int ret = -1; +char *result = NULL; +qemuDomainObjPrivatePtr priv; + +virCheckFlags(0, NULL); + +qemuDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, domain-uuid); +qemuDriverUnlock(driver); + +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(domain-uuid, uuidstr); +virReportError(VIR_ERR_NO_DOMAIN, +_(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +priv = vm-privateData; + +if (!virDomainObjIsActive(vm)) { +virReportError(VIR_ERR_OPERATION_INVALID, + %s, _(domain is not running)); +goto cleanup; +} + +if (priv-agentError) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(QEMU guest agent is not available due to an error)); +goto cleanup; +} + +if (!priv-agent) { +virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, %s, + _(QEMU guest agent is not configured)); +goto cleanup; +} + +if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) 0) +goto cleanup; + +if (!virDomainObjIsActive(vm)) { +virReportError(VIR_ERR_OPERATION_INVALID, + %s, _(domain is not running)); +goto endjob; +} + +qemuDomainObjEnterAgent(driver, vm); +ret = qemuAgentArbitraryCommand(priv-agent, cmd, result, timeout); +qemuDomainObjExitAgent(driver, vm); + +endjob: +if (qemuDomainObjEndJob(driver, vm) == 0) { +vm = NULL; +} + +cleanup: +if (vm) +virDomainObjUnlock(vm); +return result; +} + static virDriver qemuDriver = { .no = VIR_DRV_QEMU, .name = QEMU_DRIVER_NAME, @@ -13603,6 +13673,7 @@ static virDriver qemuDriver = { .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */ .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */ .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */ +.qemuDomainArbitraryAgentCommand = qemuDrvDomainAgentCommand, /* 0.10.1 */ }; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 1/7] Add @seconds variable to qemuAgentSend(). Add @seconds variable to qemuAgentSend(). When @tiemout is true, @seconds controls how long to wait for a response (if @seconds is VI
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- include/libvirt/libvirt-qemu.h |7 +++ src/qemu/qemu_agent.c | 32 ++-- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index a37f897..93386ca 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -44,6 +44,13 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain, unsigned int pid_value, unsigned int flags); +typedef enum { +VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN = -2, +VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -2, +VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT = -1, +VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, +} virDomainQemuAgentCommandTimeoutValues; + # ifdef __cplusplus } # endif diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 513f1d5..61f070c 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -837,6 +837,8 @@ void qemuAgentClose(qemuAgentPtr mon) * @mon: Monitor * @msg: Message * @timeout: use timeout? + * @seconds: timeout seconds. if VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT and + * @timeout is true, use default value. * * Send @msg to agent @mon. * Wait max QEMU_AGENT_WAIT_TIME for agent @@ -848,7 +850,8 @@ void qemuAgentClose(qemuAgentPtr mon) */ static int qemuAgentSend(qemuAgentPtr mon, qemuAgentMessagePtr msg, - bool timeout) + bool timeout, + int seconds) { int ret = -1; unsigned long long now, then = 0; @@ -864,7 +867,10 @@ static int qemuAgentSend(qemuAgentPtr mon, if (timeout) { if (virTimeMillisNow(now) 0) return -1; -then = now + QEMU_AGENT_WAIT_TIME; +if (!(seconds = 0 || seconds == VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT)) +return -1; +then = now + (seconds == VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT ? + QEMU_AGENT_WAIT_TIME : seconds * 1000ull); } mon-msg = msg; @@ -937,7 +943,8 @@ qemuAgentGuestSync(qemuAgentPtr mon) VIR_DEBUG(Sending guest-sync command with ID: %llu, id); -send_ret = qemuAgentSend(mon, sync_msg, true); +send_ret = qemuAgentSend(mon, sync_msg, true, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT); VIR_DEBUG(qemuAgentSend returned: %d, send_ret); @@ -977,7 +984,8 @@ cleanup: static int qemuAgentCommand(qemuAgentPtr mon, virJSONValuePtr cmd, - virJSONValuePtr *reply) + virJSONValuePtr *reply, + int seconds) { int ret = -1; qemuAgentMessage msg; @@ -1003,9 +1011,9 @@ qemuAgentCommand(qemuAgentPtr mon, } msg.txLength = strlen(msg.txBuffer); -VIR_DEBUG(Send command '%s' for write, cmdstr); +VIR_DEBUG(Send command '%s' for write, seconds = %d, cmdstr, seconds); -ret = qemuAgentSend(mon, msg, false); +ret = qemuAgentSend(mon, msg, seconds -1 ? false : true, seconds); VIR_DEBUG(Receive command reply ret=%d rxObject=%p, ret, msg.rxObject); @@ -1283,7 +1291,8 @@ int qemuAgentShutdown(qemuAgentPtr mon, return -1; mon-await_event = QEMU_AGENT_EVENT_SHUTDOWN; -ret = qemuAgentCommand(mon, cmd, reply); +ret = qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT); if (reply ret == 0) ret = qemuAgentCheckError(cmd, reply); @@ -1315,7 +1324,8 @@ int qemuAgentFSFreeze(qemuAgentPtr mon) if (!cmd) return -1; -if (qemuAgentCommand(mon, cmd, reply) 0 || +if (qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT) 0 || qemuAgentCheckError(cmd, reply) 0) goto cleanup; @@ -1352,7 +1362,8 @@ int qemuAgentFSThaw(qemuAgentPtr mon) if (!cmd) return -1; -if (qemuAgentCommand(mon, cmd, reply) 0 || +if (qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT) 0 || qemuAgentCheckError(cmd, reply) 0) goto cleanup; @@ -1389,7 +1400,8 @@ qemuAgentSuspend(qemuAgentPtr mon, return -1; mon-await_event = QEMU_AGENT_EVENT_SUSPEND; -ret = qemuAgentCommand(mon, cmd, reply); +ret = qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT); if (reply ret == 0) ret = qemuAgentCheckError(cmd, reply); -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 6/7] add python module support Add virDomainQemuAgentCommand() support function to python module.
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- python/libvirt-qemu-override-api.xml |8 python/libvirt-qemu-override.c | 29 + 2 files changed, 37 insertions(+), 0 deletions(-) diff --git a/python/libvirt-qemu-override-api.xml b/python/libvirt-qemu-override-api.xml index d69acea..ca0dae9 100644 --- a/python/libvirt-qemu-override-api.xml +++ b/python/libvirt-qemu-override-api.xml @@ -8,5 +8,13 @@ arg name='cmd' type='const char *' info='the command which will be passed to QEMU monitor'/ arg name='flags' type='unsigned int' info='an ORapos;ed set of virDomainQemuMonitorCommandFlags'/ /function + function name='virDomainQemuAgentCommand' file='python-qemu' +infoSend a Guest Agent command to domain/info +return type='str *' info='the command output'/ +arg name='domain' type='virDomainPtr' info='pointer to the domain'/ +arg name='cmd' type='const char *' info='guest agent command on domain'/ +arg name='timeout' type='int' info='timeout seconds'/ +arg name='flags' type='unsigned int' info='execution flags'/ + /function /symbols /api diff --git a/python/libvirt-qemu-override.c b/python/libvirt-qemu-override.c index e532416..243692a 100644 --- a/python/libvirt-qemu-override.c +++ b/python/libvirt-qemu-override.c @@ -82,6 +82,34 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, return py_retval; } +static PyObject * +libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) +{ +PyObject *py_retval; +char *result = NULL; +virDomainPtr domain; +PyObject *pyobj_domain; +int timeout; +unsigned int flags; +char *cmd; + +if (!PyArg_ParseTuple(args, (char *)Ozii:virDomainQemuAgentCommand, + pyobj_domain, cmd, timeout, flags)) +return NULL; +domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + +if (domain == NULL) +return VIR_PY_NONE; +LIBVIRT_BEGIN_ALLOW_THREADS; +result = virDomainQemuAgentCommand(domain, cmd, timeout, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (!result) +return VIR_PY_NONE; + +py_retval = PyString_FromString(result); +return py_retval; +} / * * * The registration stuff * @@ -90,6 +118,7 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, static PyMethodDef libvirtQemuMethods[] = { #include libvirt-qemu-export.c {(char *) virDomainQemuMonitorCommand, libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL}, +{(char *) virDomainQemuAgentCommand, libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 7/7] add qemu-agent-command to virsh Add qemu-agent-command to virsh to support virDomainQemuAgentCommand().
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- tools/virsh-host.c | 89 tools/virsh.pod| 13 +++ 2 files changed, 102 insertions(+), 0 deletions(-) diff --git a/tools/virsh-host.c b/tools/virsh-host.c index b09d9f9..682d374 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -633,6 +633,93 @@ cleanup: } /* + * qemu-agent-command command + */ +static const vshCmdInfo info_qemu_agent_command[] = { +{help, N_(QEMU Guest Agent Command)}, +{desc, N_(Run an arbitrary qemu guest agent command; use at your own risk)}, +{NULL, NULL} +}; + +static const vshCmdOptDef opts_qemu_agent_command[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{timeout, VSH_OT_INT, VSH_OFLAG_REQ_OPT, N_(timeout seconds. must be positive.)}, +{async, VSH_OT_BOOL, 0, N_(execute command without waiting for timeout)}, +{block, VSH_OT_BOOL, 0, N_(execute command without timeout)}, +{cmd, VSH_OT_ARGV, VSH_OFLAG_REQ, N_(command)}, +{NULL, 0, 0, NULL} +}; + +static bool +cmdQemuAgentCommand(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom = NULL; +bool ret = false; +char *guest_agent_cmd = NULL; +char *result = NULL; +int timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT; +int judge = 0; +unsigned int flags = 0; +const vshCmdOpt *opt = NULL; +virBuffer buf = VIR_BUFFER_INITIALIZER; +bool pad = false; + +if (!vshConnectionUsability(ctl, ctl-conn)) +goto cleanup; + +dom = vshCommandOptDomain(ctl, cmd, NULL); +if (dom == NULL) +goto cleanup; + +while ((opt = vshCommandOptArgv(cmd, opt))) { +if (pad) +virBufferAddChar(buf, ' '); +pad = true; +virBufferAdd(buf, opt-data, -1); +} +if (virBufferError(buf)) { +vshPrint(ctl, %s, _(Failed to collect command)); +goto cleanup; +} +guest_agent_cmd = virBufferContentAndReset(buf); + +judge = vshCommandOptInt(cmd, timeout, timeout); +if (judge 0) { +vshError(ctl, %s, _(timeout number has to be a number)); +} else if (judge 0) { +judge = 1; +} +if (judge timeout 1) { +vshError(ctl, %s, _(timeout must be positive)); +} + +if (vshCommandOptBool(cmd, async)) { +timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT; +judge++; +} +if (vshCommandOptBool(cmd, block)) { +timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK; +judge++; +} + +if (judge 1) { +vshError(ctl, %s, _(timeout, async and block options are exclusive)); +} +result = virDomainQemuAgentCommand(dom, guest_agent_cmd, timeout, flags); + +if (result) printf(%s\n, result); + +ret = true; + +cleanup: +VIR_FREE(result); +VIR_FREE(guest_agent_cmd); +if (dom) +virDomainFree(dom); + +return ret; +} +/* * sysinfo command */ static const vshCmdInfo info_sysinfo[] = { @@ -832,6 +919,8 @@ static const vshCmdDef hostAndHypervisorCmds[] = { {qemu-attach, cmdQemuAttach, opts_qemu_attach, info_qemu_attach, 0}, {qemu-monitor-command, cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command, 0}, +{qemu-agent-command, cmdQemuAgentCommand, opts_qemu_agent_command, + info_qemu_agent_command, 0}, {sysinfo, cmdSysinfo, NULL, info_sysinfo, 0}, {uri, cmdURI, NULL, info_uri, 0}, {version, cmdVersion, opts_version, info_version, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 35613c4..f997cb4 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -164,6 +164,7 @@ group as an option. For example: hostname print the hypervisor hostname qemu-attachAttach to existing QEMU process qemu-monitor-command QEMU Monitor Command + qemu-agent-command QEMU Guest Agent Command sysinfoprint the hypervisor sysinfo uriprint the hypervisor canonical URI @@ -2780,6 +2781,18 @@ before passing the single command to the monitor. =back +=item Bqemu-agent-command Idomain [I--timeout Iseconds | I--async | I--block] Icommand... + +Send an arbitrary guest agent command Icommand to domain Idomain through +qemu agent. +I--timeout, I--async and I--block options are exclusive. +I--timeout requires timeout seconds Iseconds and it must be positive. +When I--aysnc is given, the command waits for timeout whether success or +failed. And when I--block is given, the command waits forever with blocking +timeout. + +=back + =head1 ENVIRONMENT The following environment variables can be set to alter the behaviour -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 2/7] add qemuAgentArbitraryCommand() for general qemu agent command. add qemuAgentArbitraryCommand() for general qemu agent command.
Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- src/qemu/qemu_agent.c | 30 ++ src/qemu/qemu_agent.h |5 + 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 61f070c..c658bf8 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1410,3 +1410,33 @@ qemuAgentSuspend(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +int +qemuAgentArbitraryCommand(qemuAgentPtr mon, + const char *cmd_str, + char **result, + int timeout) +{ +int ret = -1; +virJSONValuePtr cmd; +virJSONValuePtr reply = NULL; + +*result = NULL; +if (timeout VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN) +return ret; + +cmd = virJSONValueFromString(cmd_str); +if (!cmd) +return ret; + +ret = qemuAgentCommand(mon, cmd, reply, timeout); + +if (ret == 0) { +ret = qemuAgentCheckError(cmd, reply); +*result = virJSONValueToString(reply, false); +} + +virJSONValueFree(cmd); +virJSONValueFree(reply); +return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 2fdebb2..528fee1 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -77,4 +77,9 @@ int qemuAgentFSThaw(qemuAgentPtr mon); int qemuAgentSuspend(qemuAgentPtr mon, unsigned int target); + +int qemuAgentArbitraryCommand(qemuAgentPtr mon, + const char *cmd, + char **result, + int timeout); #endif /* __QEMU_AGENT_H__ */ -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/7] Add @seconds vaiable to qemuAgentSend()
(2012/08/16 21:58), Martin Kletzander wrote: On 08/15/2012 03:36 AM, MATSUDA Daiki wrote: Add @seconds variable to qemuAgentSend(). When @tiemout is true, @seconds controls how long to wait for a response (if @seconds is VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, default to QEMU_AGENT_WAIT_TIME). If @timeout is false, @seconds is ignored. Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- include/libvirt/libvirt-qemu.h |6 ++ src/qemu/qemu_agent.c | 30 -- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index a37f897..013ed5a 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -44,6 +44,12 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain, unsigned int pid_value, unsigned int flags); +typedef enum { +VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -2, Correct me if I'm wrong, but isn't this the same as setting timeout to false? Yes, it is same that @timeout = false to qemuAgentSend() from qemuAgentCommand(). +VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT = -1, +VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, +} virDomainQemuAgentCommandTimeoutValues; + # ifdef __cplusplus } # endif diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 15af758..26c2726 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -837,6 +837,8 @@ void qemuAgentClose(qemuAgentPtr mon) * @mon: Monitor * @msg: Message * @timeout: use timeout? + * @seconds: timeout seconds. if VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT and + * @timeout is true, use default value. If my previous assumption is correct, than the timeout parameter can be completely thrown away. @seconds is effective uder the situation @timeout = true. Then @seconds must be 0. But @seconds = 0, it is dangerous. I do not understand whether it is needed, but other people discussed. https://www.redhat.com/archives/libvir-list/2012-July/msg00603.html * * Send @msg to agent @mon. * Wait max QEMU_AGENT_WAIT_TIME for agent @@ -848,7 +850,8 @@ void qemuAgentClose(qemuAgentPtr mon) */ static int qemuAgentSend(qemuAgentPtr mon, qemuAgentMessagePtr msg, - bool timeout) + bool timeout, + int seconds) { int ret = -1; unsigned long long now, then = 0; @@ -864,7 +867,8 @@ static int qemuAgentSend(qemuAgentPtr mon, if (timeout) { if (virTimeMillisNow(now) 0) return -1; -then = now + QEMU_AGENT_WAIT_TIME; +then = now + (seconds == VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT ? + QEMU_AGENT_WAIT_TIME : seconds * 1000ull); } Also if seconds == VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK, then this causes 'then' to be smaller than now. I'm not sure what that would do with pthread_cond_timedwait, but that's definitely not wanted behavior. Its situation is blocked on calling qemuAgentSend() from qemuAgentCommand(). But qemuAgentSend() may also have the block code. Martin -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/7] add virAgentCommand()
(2012/08/16 22:13), Martin Kletzander wrote: On 08/15/2012 03:36 AM, MATSUDA Daiki wrote: diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index 013ed5a..60b83ef 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -50,6 +50,9 @@ typedef enum { VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, } virDomainQemuAgentCommandTimeoutValues; +char *virAgentCommand(virDomainPtr domain, const char *cmd, + int timeout, unsigned int flags); + I wondered why this is type 'char *', when we can use 'int' as usual and have '**result' (same as monitor command does). It depends on generating the code automatically Eric suggested. It decides the returning type. diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c index 78480bb..49dfc20 100644 --- a/src/libvirt-qemu.c +++ b/src/libvirt-qemu.c @@ -185,3 +185,54 @@ error: virDispatchError(conn); return NULL; } + +/** + * virAgentCommand: + * @domain: a domain object + * @cmd: the guest agent command string + * @timeout: timeout seconds + * @flags: execution flags + * + * Execute an arbitrary Guest Agent command. + * + * Issue @cmd to the guest agent running in @domain. + * If @result is NULL, then don't wait for a result (and @timeout And then I noticed that there is no @result here, so maybe you wanted to make it that way and didn't change something? It is my mistake. + * must be 0). Otherwise, wait for @timeout seconds for a + * @timeout must be -2, -1, 0 or positive. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK(-2): meaning to block forever waiting for + * a result. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT(-1): use default timeout value. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT(0): does not wait. + * positive value: wait for @timeout seconds + * + * Returns strings if success, NULL in failure. + */ +char * +virAgentCommand(virDomainPtr domain, +const char *cmd, +int timeout, +unsigned int flags) +{ +virConnectPtr conn; + +VIR_DEBUG(domain=%p, cmd=%s, timeout=%d, flags=%x, + domain, cmd, timeout, flags); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return NULL; +} + +conn = domain-conn; + +if (conn-driver-qemuAgentCommand) { +return conn-driver-qemuAgentCommand(domain, cmd, timeout, flags); Shouldn't this be allowed only for read-only connections? I do not uderstand what you say. +} + +virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +/* Copy to connection error object for back compatability */ s/compatability/compatibility/ +virDispatchError(domain-conn); You have 'domain-conn' in 'conn' already. Martin -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 5/7] add qemuAgentCommand() for .qemuAgentCommand to remote driver
(2012/08/16 22:25), Martin Kletzander wrote: On 08/15/2012 03:36 AM, MATSUDA Daiki wrote: diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 353a153..3c60709 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -5368,6 +5368,7 @@ static virDriver remote_driver = { .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */ .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */ .domainGetHostname = remoteDomainGetHostname, /* 0.10.0 */ +.qemuAgentCommand = qemuAgentCommand, /* 0.10.0 */ You probably want to call some function like 'remoteQemuDomainAgentCommand' or something like that since qemuAgentCommand works locally and not remotely. Yes. But the function name is generated automatically from QEMU_RPOC_AGNET_COMMAND. And I will change it on next version. So, do you have suggestion name? qemuDomainAgentCommand() from QEMU_PROC_DOMAIN_AGENT_COMMAND ? I haven't had a look at the rest of the series. Please feel free to correct me in case I've misunderstood the code somewhere. Martin -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/7] support guest agent general command v3
Hi. All. I rewrote the patched. But I modified the feature for the situation @result pointer is NULL. Though before it does not forcely wait, I think it is not meanless because @result pointer is always NULL. And @timeout must be following VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK(-2) : does not block and wait forever. VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT(-1) : use default time for waiting VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWIAT(0) : does not wait and out soon positive value : wait for pointed seconds. In addition, I added the some options for virsh command qemu-agent-command --block : it means taht @timeout is VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK. --async : it means taht @timeout is VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWIAT. --timeout @seconds : @seconds must be positive value and it means that @timeout is positive value case. These upper options are exclusive. If no options are given, it means taht @timeout is IR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT. virsh # help qemu-agent-command NAME qemu-agent-command - QEMU Guest Agent Command SYNOPSIS qemu-agent-command domain [--timeout number] [--async] [--block] {[--cmd] string}... DESCRIPTION Run an arbitrary qemu guest agent command; use at your own risk OPTIONS [--domain] string domain name, id or uuid --timeout number timeout seconds. must be positive. --async execute command without waiting for timeout --block execute command without timeout [--cmd] string command virsh # qemu-agent-command RHEL58_64 '{execute:guest-info}' {return:{version:1.1.50,supported_commands:[{enabled:true,name:guest-network-get-interfaces},{enabled:true,name:guest-suspend-hybrid},{enabled:true,name:guest-suspend-ram},{enabled:true,name:guest-suspend-disk},{enabled:true,name:guest-fsfreeze-thaw},{enabled:true,name:guest-fsfreeze-freeze},{enabled:true,name:guest-fsfreeze-status},{enabled:true,name:guest-file-flush},{enabled:true,name:guest-file-seek},{enabled:true,name:guest-file-write},{enabled:true,name:guest-file-read},{enabled:true,name:guest-file-close},{enabled:true,name:guest-file-open},{enabled:true,name:guest-shutdown},{enabled:true,name:guest-info},{enabled:true,name:guest-ping},{enabled:true,name:guest-sync},{enabled:true,name:guest-sync-delimited}]}} virsh # qemu-agent-command --block RHEL58_64 '{execute:guest-sync,arguments:{id:123}}' {return:123} -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/7] Add @seconds vaiable to qemuAgentSend()
Add @seconds variable to qemuAgentSend(). When @tiemout is true, @seconds controls how long to wait for a response (if @seconds is VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, default to QEMU_AGENT_WAIT_TIME). If @timeout is false, @seconds is ignored. Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- include/libvirt/libvirt-qemu.h |6 ++ src/qemu/qemu_agent.c | 30 -- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index a37f897..013ed5a 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -44,6 +44,12 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain, unsigned int pid_value, unsigned int flags); +typedef enum { +VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -2, +VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT = -1, +VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, +} virDomainQemuAgentCommandTimeoutValues; + # ifdef __cplusplus } # endif diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 15af758..26c2726 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -837,6 +837,8 @@ void qemuAgentClose(qemuAgentPtr mon) * @mon: Monitor * @msg: Message * @timeout: use timeout? + * @seconds: timeout seconds. if VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT and + * @timeout is true, use default value. * * Send @msg to agent @mon. * Wait max QEMU_AGENT_WAIT_TIME for agent @@ -848,7 +850,8 @@ void qemuAgentClose(qemuAgentPtr mon) */ static int qemuAgentSend(qemuAgentPtr mon, qemuAgentMessagePtr msg, - bool timeout) + bool timeout, + int seconds) { int ret = -1; unsigned long long now, then = 0; @@ -864,7 +867,8 @@ static int qemuAgentSend(qemuAgentPtr mon, if (timeout) { if (virTimeMillisNow(now) 0) return -1; -then = now + QEMU_AGENT_WAIT_TIME; +then = now + (seconds == VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT ? + QEMU_AGENT_WAIT_TIME : seconds * 1000ull); } mon-msg = msg; @@ -937,7 +941,8 @@ qemuAgentGuestSync(qemuAgentPtr mon) VIR_DEBUG(Sending guest-sync command with ID: %llu, id); -send_ret = qemuAgentSend(mon, sync_msg, true); +send_ret = qemuAgentSend(mon, sync_msg, true, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT); VIR_DEBUG(qemuAgentSend returned: %d, send_ret); @@ -977,7 +982,8 @@ cleanup: static int qemuAgentCommand(qemuAgentPtr mon, virJSONValuePtr cmd, - virJSONValuePtr *reply) + virJSONValuePtr *reply, + int seconds) { int ret = -1; qemuAgentMessage msg; @@ -1003,9 +1009,9 @@ qemuAgentCommand(qemuAgentPtr mon, } msg.txLength = strlen(msg.txBuffer); -VIR_DEBUG(Send command '%s' for write, cmdstr); +VIR_DEBUG(Send command '%s' for write, seconds = %d, cmdstr, seconds); -ret = qemuAgentSend(mon, msg, false); +ret = qemuAgentSend(mon, msg, seconds -1 ? false : true, seconds); VIR_DEBUG(Receive command reply ret=%d rxObject=%p, ret, msg.rxObject); @@ -1283,7 +1289,8 @@ int qemuAgentShutdown(qemuAgentPtr mon, return -1; mon-await_event = QEMU_AGENT_EVENT_SHUTDOWN; -ret = qemuAgentCommand(mon, cmd, reply); +ret = qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT); if (reply ret == 0) ret = qemuAgentCheckError(cmd, reply); @@ -1315,7 +1322,8 @@ int qemuAgentFSFreeze(qemuAgentPtr mon) if (!cmd) return -1; -if (qemuAgentCommand(mon, cmd, reply) 0 || +if (qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT) 0 || qemuAgentCheckError(cmd, reply) 0) goto cleanup; @@ -1352,7 +1360,8 @@ int qemuAgentFSThaw(qemuAgentPtr mon) if (!cmd) return -1; -if (qemuAgentCommand(mon, cmd, reply) 0 || +if (qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT) 0 || qemuAgentCheckError(cmd, reply) 0) goto cleanup; @@ -1389,7 +1398,8 @@ qemuAgentSuspend(qemuAgentPtr mon, return -1; mon-await_event = QEMU_AGENT_EVENT_SUSPEND; -ret = qemuAgentCommand(mon, cmd, reply); +ret = qemuAgentCommand(mon, cmd, reply, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT); if (reply ret == 0) ret = qemuAgentCheckError(cmd, reply); -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 3/7] add virAgentCommand()
Add virDrvAgentCommand prototype for drivers. Add virAgentCommand() for virDrvAgentCommand. Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- include/libvirt/libvirt-qemu.h |3 ++ python/generator.py|1 + src/driver.h |4 +++ src/libvirt-qemu.c | 51 src/libvirt_qemu.syms |5 5 files changed, 64 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index 013ed5a..60b83ef 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -50,6 +50,9 @@ typedef enum { VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, } virDomainQemuAgentCommandTimeoutValues; +char *virAgentCommand(virDomainPtr domain, const char *cmd, + int timeout, unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/python/generator.py b/python/generator.py index 6559ece..68758ad 100755 --- a/python/generator.py +++ b/python/generator.py @@ -431,6 +431,7 @@ skip_impl = ( qemu_skip_impl = ( 'virDomainQemuMonitorCommand', +'virAgentCommand', ) diff --git a/src/driver.h b/src/driver.h index aab9766..b780e45 100644 --- a/src/driver.h +++ b/src/driver.h @@ -688,6 +688,9 @@ typedef int typedef int (*virDrvDomainQemuMonitorCommand)(virDomainPtr domain, const char *cmd, char **result, unsigned int flags); +typedef char * +(*virDrvAgentCommand)(virDomainPtr domain, const char *cmd, + int timeout, unsigned int flags); /* Choice of unsigned int rather than pid_t is intentional. */ typedef virDomainPtr @@ -1048,6 +1051,7 @@ struct _virDriver { virDrvDomainGetDiskErrors domainGetDiskErrors; virDrvDomainSetMetadata domainSetMetadata; virDrvDomainGetMetadata domainGetMetadata; +virDrvAgentCommand qemuAgentCommand; }; typedef int diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c index 78480bb..49dfc20 100644 --- a/src/libvirt-qemu.c +++ b/src/libvirt-qemu.c @@ -185,3 +185,54 @@ error: virDispatchError(conn); return NULL; } + +/** + * virAgentCommand: + * @domain: a domain object + * @cmd: the guest agent command string + * @timeout: timeout seconds + * @flags: execution flags + * + * Execute an arbitrary Guest Agent command. + * + * Issue @cmd to the guest agent running in @domain. + * If @result is NULL, then don't wait for a result (and @timeout + * must be 0). Otherwise, wait for @timeout seconds for a + * @timeout must be -2, -1, 0 or positive. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK(-2): meaning to block forever waiting for + * a result. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT(-1): use default timeout value. + * VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT(0): does not wait. + * positive value: wait for @timeout seconds + * + * Returns strings if success, NULL in failure. + */ +char * +virAgentCommand(virDomainPtr domain, +const char *cmd, +int timeout, +unsigned int flags) +{ +virConnectPtr conn; + +VIR_DEBUG(domain=%p, cmd=%s, timeout=%d, flags=%x, + domain, cmd, timeout, flags); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return NULL; +} + +conn = domain-conn; + +if (conn-driver-qemuAgentCommand) { +return conn-driver-qemuAgentCommand(domain, cmd, timeout, flags); +} + +virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +/* Copy to connection error object for back compatability */ +virDispatchError(domain-conn); +return NULL; +} diff --git a/src/libvirt_qemu.syms b/src/libvirt_qemu.syms index 8447730..f1a4bb4 100644 --- a/src/libvirt_qemu.syms +++ b/src/libvirt_qemu.syms @@ -19,3 +19,8 @@ LIBVIRT_QEMU_0.9.4 { global: virDomainQemuAttach; } LIBVIRT_QEMU_0.8.3; + +LIBVIRT_QEMU_0.10.0 { +global: +virAgentCommand; +} LIBVIRT_QEMU_0.9.4; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 6/7] Add virAgentCommand() support function to python module
Add virAgentCommand() support function to python module. Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- python/libvirt-qemu-override-api.xml |8 python/libvirt-qemu-override.c | 29 + 2 files changed, 37 insertions(+), 0 deletions(-) diff --git a/python/libvirt-qemu-override-api.xml b/python/libvirt-qemu-override-api.xml index d69acea..7a31b0e 100644 --- a/python/libvirt-qemu-override-api.xml +++ b/python/libvirt-qemu-override-api.xml @@ -8,5 +8,13 @@ arg name='cmd' type='const char *' info='the command which will be passed to QEMU monitor'/ arg name='flags' type='unsigned int' info='an ORapos;ed set of virDomainQemuMonitorCommandFlags'/ /function + function name='virAgentCommand' file='python-qemu' +infoSend a Guest Agent command to domain/info +return type='str *' info='the command output'/ +arg name='domain' type='virDomainPtr' info='pointer to the domain'/ +arg name='cmd' type='const char *' info='guest agent command on domain'/ +arg name='timeout' type='int' info='timeout seconds'/ +arg name='flags' type='unsigned int' info='execution flags'/ + /function /symbols /api diff --git a/python/libvirt-qemu-override.c b/python/libvirt-qemu-override.c index e532416..738b2da 100644 --- a/python/libvirt-qemu-override.c +++ b/python/libvirt-qemu-override.c @@ -82,6 +82,34 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, return py_retval; } +static PyObject * +libvirt_qemu_virAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) +{ +PyObject *py_retval; +char *result = NULL; +virDomainPtr domain; +PyObject *pyobj_domain; +int timeout; +unsigned int flags; +char *cmd; + +if (!PyArg_ParseTuple(args, (char *)Ozii:virAgentCommand, + pyobj_domain, cmd, timeout, flags)) +return NULL; +domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + +if (domain == NULL) +return VIR_PY_NONE; +LIBVIRT_BEGIN_ALLOW_THREADS; +result = virDomainQemuAgentCommand(domain, cmd, timeout, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (!result) +return VIR_PY_NONE; + +py_retval = PyString_FromString(result); +return py_retval; +} / * * * The registration stuff * @@ -90,6 +118,7 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, static PyMethodDef libvirtQemuMethods[] = { #include libvirt-qemu-export.c {(char *) virDomainQemuMonitorCommand, libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL}, +{(char *) virAgentCommand, libvirt_qemu_virAgentCommand, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/7] add qemuAgentArbitraryCommand() for general qemu agent command.
add qemuAgentArbitraryCommand() for general qemu agent command. Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- src/qemu/qemu_agent.c | 31 +++ src/qemu/qemu_agent.h |5 + 2 files changed, 36 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 26c2726..c634c23 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1408,3 +1408,34 @@ qemuAgentSuspend(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +int +qemuAgentArbitraryCommand(qemuAgentPtr mon, + const char *cmd_str, + char **result, + int timeout) +{ +int ret = -1; +virJSONValuePtr cmd; +virJSONValuePtr reply = NULL; + +if (timeout -2) +return ret; + +cmd = virJSONValueFromString(cmd_str); +if (!cmd) +return ret; + +ret = qemuAgentCommand(mon, cmd, reply, timeout); + +if (ret == 0) { +ret = qemuAgentCheckError(cmd, reply); +*result = virJSONValueToString(reply); +} else { +result = NULL; +} + +virJSONValueFree(cmd); +virJSONValueFree(reply); +return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 2fdebb2..528fee1 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -77,4 +77,9 @@ int qemuAgentFSThaw(qemuAgentPtr mon); int qemuAgentSuspend(qemuAgentPtr mon, unsigned int target); + +int qemuAgentArbitraryCommand(qemuAgentPtr mon, + const char *cmd, + char **result, + int timeout); #endif /* __QEMU_AGENT_H__ */ -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 7/7] Add qemu-agent-command to virsh to support virAgentCommand()
Add qemu-agent-command to virsh to support virAgentCommand(). Signed-off-by: MATSUDA Daiki matsuda...@intellilink.co.jp --- tools/virsh-host.c | 89 tools/virsh.pod| 13 +++ 2 files changed, 102 insertions(+), 0 deletions(-) diff --git a/tools/virsh-host.c b/tools/virsh-host.c index d9d09b4..d302e19 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -633,6 +633,93 @@ cleanup: } /* + * qemu-agent-command command + */ +static const vshCmdInfo info_qemu_agent_command[] = { +{help, N_(QEMU Guest Agent Command)}, +{desc, N_(Run an arbitrary qemu guest agent command; use at your own risk)}, +{NULL, NULL} +}; + +static const vshCmdOptDef opts_qemu_agent_command[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{timeout, VSH_OT_INT, VSH_OFLAG_REQ_OPT, N_(timeout seconds. must be positive.)}, +{async, VSH_OT_BOOL, 0, N_(execute command without waiting for timeout)}, +{block, VSH_OT_BOOL, 0, N_(execute command without timeout)}, +{cmd, VSH_OT_ARGV, VSH_OFLAG_REQ, N_(command)}, +{NULL, 0, 0, NULL} +}; + +static bool +cmdQemuAgentCommand(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom = NULL; +bool ret = false; +char *guest_agent_cmd = NULL; +char *result = NULL; +int timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT; +int judge = 0; +unsigned int flags = 0; +const vshCmdOpt *opt = NULL; +virBuffer buf = VIR_BUFFER_INITIALIZER; +bool pad = false; + +if (!vshConnectionUsability(ctl, ctl-conn)) +goto cleanup; + +dom = vshCommandOptDomain(ctl, cmd, NULL); +if (dom == NULL) +goto cleanup; + +while ((opt = vshCommandOptArgv(cmd, opt))) { +if (pad) +virBufferAddChar(buf, ' '); +pad = true; +virBufferAdd(buf, opt-data, -1); +} +if (virBufferError(buf)) { +vshPrint(ctl, %s, _(Failed to collect command)); +goto cleanup; +} +guest_agent_cmd = virBufferContentAndReset(buf); + +judge = vshCommandOptInt(cmd, timeout, timeout); +if (judge 0) { +vshError(ctl, %s, _(timeout number has to be a number)); +} else if (judge 0) { +judge = 1; +} +if (judge timeout 1) { +vshError(ctl, %s, _(timeout must be positive)); +} + +if (vshCommandOptBool(cmd, async)) { +timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT; +judge++; +} +if (vshCommandOptBool(cmd, block)) { +timeout = VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK; +judge++; +} + +if (judge 1) { +vshError(ctl, %s, _(timeout, async and block options are exclusive)); +} +result = virAgentCommand(dom, guest_agent_cmd, timeout, flags); + +if (result) printf(%s\n, result); + +ret = true; + +cleanup: +VIR_FREE(result); +VIR_FREE(guest_agent_cmd); +if (dom) +virDomainFree(dom); + +return ret; +} +/* * sysinfo command */ static const vshCmdInfo info_sysinfo[] = { @@ -832,6 +919,8 @@ static const vshCmdDef hostAndHypervisorCmds[] = { {qemu-attach, cmdQemuAttach, opts_qemu_attach, info_qemu_attach, 0}, {qemu-monitor-command, cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command, 0}, +{qemu-agent-command, cmdQemuAgentCommand, opts_qemu_agent_command, + info_qemu_agent_command, 0}, {sysinfo, cmdSysinfo, NULL, info_sysinfo, 0}, {uri, cmdURI, NULL, info_uri, 0}, {version, cmdVersion, opts_version, info_version, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 35613c4..f997cb4 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -164,6 +164,7 @@ group as an option. For example: hostname print the hypervisor hostname qemu-attachAttach to existing QEMU process qemu-monitor-command QEMU Monitor Command + qemu-agent-command QEMU Guest Agent Command sysinfoprint the hypervisor sysinfo uriprint the hypervisor canonical URI @@ -2780,6 +2781,18 @@ before passing the single command to the monitor. =back +=item Bqemu-agent-command Idomain [I--timeout Iseconds | I--async | I--block] Icommand... + +Send an arbitrary guest agent command Icommand to domain Idomain through +qemu agent. +I--timeout, I--async and I--block options are exclusive. +I--timeout requires timeout seconds Iseconds and it must be positive. +When I--aysnc is given, the command waits for timeout whether success or +failed. And when I--block is given, the command waits forever with blocking +timeout. + +=back + =head1 ENVIRONMENT The following environment variables can be set to alter the behaviour -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/5] add qemuAgentCommand()
(2012/08/09 11:08), Eric Blake wrote: On 08/07/2012 06:04 PM, MATSUDA, Daiki wrote: Add qemuAgentCommand() for general qemu agent command. include/libvirt/libvirt-qemu.h |5 + src/qemu/qemu_agent.c | 38 ++ src/qemu/qemu_agent.h |5 + 3 files changed, 48 insertions(+) Causes a compiler warning: CC libvirt_driver_qemu_impl_la-qemu_agent.lo qemu/qemu_agent.c: In function 'qemuAgentQemuAgentCommand': qemu/qemu_agent.c:1411:9: error: variable 'seconds' set but not used [-Werror=unused-but-set-variable] Sorry, it has a mistake on calling qemuAgentCommand() with not seconds but timeout. diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index a37f897..ffc5ae5 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -44,6 +44,11 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain, unsigned int pid_value, unsigned int flags); +typedef enum { +VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -1, +VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, +} virDomainQemuAgentCommandTimeoutFlags; These aren't flags, but special timeout values. Maybe s/Flags/Values/ + +int qemuAgentQemuAgentCommand(qemuAgentPtr mon, This name sounds funny; maybe qemuAgentArbitraryCommand might be nicer. + const char *cmd_str, + char **result, + int timeout) +{ +int ret = -1; +int seconds; +virJSONValuePtr cmd; +virJSONValuePtr reply = NULL; + +cmd = virJSONValueFromString(cmd_str); +if (!cmd) +return ret; + +if (result == NULL) { +seconds = 0; +} else if (timeout == VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) { +seconds = 5; Why 5 seconds here, Becuase I realize the infinite waiting as you suggested. * If @result is NULL, then don't wait for a result (and @timeout * must be 0). Otherwise, wait for @timeout seconds for a * successful result to be populated into *@result, with * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK (-1) meaning to block * forever waiting for a result. But it is difficult. So, I used 'repeat' tag and 5 seconds is default value. #define QEMU_AGENT_WAIT_TIME (1000ull * 5) +} else { +seconds = timeout; but the user's timeout here? If you are looping while waiting for a response, then 5 seconds is too long between loops; you will feel unresponsive; and if the user passes a timeout of 10, you end up waiting 10 seconds. +} + +repeat: +ret = qemuAgentCommand(mon, cmd, reply, timeout); Won't work - this starts a new agent command every time repeat is reached, rather than waiting for the completion of an existing command. + +if (ret == 0) { +ret = qemuAgentCheckError(cmd, reply); +*result = virJSONValueToString(reply); +} else { +if (timeout == VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) goto repeat; Typical formatting would be to split this to two lines: if (timeout == VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) goto repeat; +*result = NULL; +} + +virJSONValueFree(cmd); +virJSONValueFree(reply); +return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 2fdebb2..fc19c2f 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -77,4 +77,9 @@ int qemuAgentFSThaw(qemuAgentPtr mon); int qemuAgentSuspend(qemuAgentPtr mon, unsigned int target); + +int qemuAgentQemuAgentCommand(qemuAgentPtr mon, + const char *cmd, + char **result, + int timeout); #endif /* __QEMU_AGENT_H__ */ Definitely needs some work before this function will handle timeout properly. And I attached fixed patch, but it is not completed. After receiving all comments, I will resend new patches. include/libvirt/libvirt-qemu.h |5 src/qemu/qemu_agent.c | 47 - src/qemu/qemu_agent.h |5 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index a37f897..ffc5ae5 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -44,6 +44,11 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain, unsigned int pid_value, unsigned int flags); +typedef enum { +VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -1, +VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, +} virDomainQemuAgentCommandTimeoutValues; + # ifdef __cplusplus } # endif diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 7699042..1cfcafc 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu
[libvirt] [PATCH 2/5] add qemuAgentCommand()
Add qemuAgentCommand() for general qemu agent command. include/libvirt/libvirt-qemu.h |5 + src/qemu/qemu_agent.c | 38 ++ src/qemu/qemu_agent.h |5 + 3 files changed, 48 insertions(+) diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index a37f897..ffc5ae5 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -44,6 +44,11 @@ virDomainPtr virDomainQemuAttach(virConnectPtr domain, unsigned int pid_value, unsigned int flags); +typedef enum { +VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK = -1, +VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, +} virDomainQemuAgentCommandTimeoutFlags; + # ifdef __cplusplus } # endif diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 7699042..1cfcafc 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1401,3 +1401,41 @@ qemuAgentSuspend(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +int qemuAgentQemuAgentCommand(qemuAgentPtr mon, + const char *cmd_str, + char **result, + int timeout) +{ +int ret = -1; +int seconds; +virJSONValuePtr cmd; +virJSONValuePtr reply = NULL; + +cmd = virJSONValueFromString(cmd_str); +if (!cmd) +return ret; + +if (result == NULL) { +seconds = 0; +} else if (timeout == VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) { +seconds = 5; +} else { +seconds = timeout; +} + +repeat: +ret = qemuAgentCommand(mon, cmd, reply, timeout); + +if (ret == 0) { +ret = qemuAgentCheckError(cmd, reply); +*result = virJSONValueToString(reply); +} else { +if (timeout == VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) goto repeat; +*result = NULL; +} + +virJSONValueFree(cmd); +virJSONValueFree(reply); +return ret; +} diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 2fdebb2..fc19c2f 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -77,4 +77,9 @@ int qemuAgentFSThaw(qemuAgentPtr mon); int qemuAgentSuspend(qemuAgentPtr mon, unsigned int target); + +int qemuAgentQemuAgentCommand(qemuAgentPtr mon, + const char *cmd, + char **result, + int timeout); #endif /* __QEMU_AGENT_H__ */ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 3/5] add virDomainQemuAgentCommand() to qemu driver and remote driver
Add virDomainQemuAgentCommand() to qemu driver and remote driver to support qemuAgentCommand(). daemon/remote.c| 35 include/libvirt/libvirt-qemu.h |3 + src/driver.h |6 +++ src/libvirt-qemu.c | 58 + src/libvirt_qemu.syms |5 ++ src/qemu/qemu_driver.c | 71 + src/qemu_protocol-structs | 10 + src/remote/qemu_protocol.x | 14 +++- src/remote/remote_driver.c | 41 +++ 9 files changed, 242 insertions(+), 1 deletion(-) diff --git a/daemon/remote.c b/daemon/remote.c index 832307e..4fd5c9b 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -3948,6 +3948,41 @@ cleanup: return rv; } +static int +qemuDispatchAgentCommand(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + qemu_agent_command_args *args, + qemu_agent_command_ret *ret) +{ +virDomainPtr dom = NULL; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; + +if (virDomainQemuAgentCommand(dom, args-cmd, ret-result, + args-timeout, args-flags) 0) { +goto cleanup; +} + +rv = 0; +cleanup: +if (rv 0) +virNetMessageSaveError(rerr); +if (dom) +virDomainFree(dom); +return rv; +} + /*- Helpers. -*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/include/libvirt/libvirt-qemu.h b/include/libvirt/libvirt-qemu.h index ffc5ae5..aed1259 100644 --- a/include/libvirt/libvirt-qemu.h +++ b/include/libvirt/libvirt-qemu.h @@ -49,6 +49,9 @@ typedef enum { VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT = 0, } virDomainQemuAgentCommandTimeoutFlags; +int virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd, + char **result, int timeout, unsigned int flags); + # ifdef __cplusplus } # endif diff --git a/src/driver.h b/src/driver.h index aab9766..c368273 100644 --- a/src/driver.h +++ b/src/driver.h @@ -689,6 +689,11 @@ typedef int (*virDrvDomainQemuMonitorCommand)(virDomainPtr domain, const char *cmd, char **result, unsigned int flags); +typedef int +(*virDrvDomainQemuAgentCommand)(virDomainPtr domain, const char *cmd, +char **result, int timeout, +unsigned int flags); + /* Choice of unsigned int rather than pid_t is intentional. */ typedef virDomainPtr (*virDrvDomainQemuAttach)(virConnectPtr conn, @@ -1048,6 +1053,7 @@ struct _virDriver { virDrvDomainGetDiskErrors domainGetDiskErrors; virDrvDomainSetMetadata domainSetMetadata; virDrvDomainGetMetadata domainGetMetadata; +virDrvDomainQemuAgentCommandqemuDomainQemuAgentCommand; }; typedef int diff --git a/src/libvirt-qemu.c b/src/libvirt-qemu.c index 78480bb..0e12425 100644 --- a/src/libvirt-qemu.c +++ b/src/libvirt-qemu.c @@ -185,3 +185,61 @@ error: virDispatchError(conn); return NULL; } + +/** + * virDomainQemuAgentCommand: + * @domain: a domain object + * @cmd: the guest agent command string + * @result: a string returned by @cmd + * @timeout: timeout seconds + * @flags: execution flags + * + * Execution Guest Agent Command + * + * Issue @cmd to the guest agent running in @domain. + * If @result is NULL, then don't wait for a result (and @timeout + * must be 0). Otherwise, wait for @timeout seconds for a + * successful result to be populated into *@result, with + * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK (-1) meaning to block + * forever waiting for a result. + * + * Returns 0 if succeeded, -1 in failing. + */ +int +virDomainQemuAgentCommand(virDomainPtr domain, + const char *cmd, + char **result, + int timeout, + unsigned int flags) +{ +virConnectPtr conn; + +VIR_DEBUG(domain=%p, cmd=%s, result=%p, timeout=%d, flags=%x, + domain, cmd, result, timeout, flags); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} + +conn = domain-conn; + +virCheckNonNullArgGoto(result, error); + +if (conn-driver-qemuDomainQemuAgentCommand) { +int ret; +ret =
[libvirt] [PATCH 5/5] Add qemu-agent-command command to virsh
Add qemu-agent-command command to virsh to support virDomainQemuAgentCommand(). virsh-host.c | 70 +++ 1 file changed, 70 insertions(+) diff --git a/tools/virsh-host.c b/tools/virsh-host.c index d9d09b4..b9180f3 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -633,6 +633,74 @@ cleanup: } /* + * qemu-agent-command command + */ +static const vshCmdInfo info_qemu_agent_command[] = { +{help, N_(Qemu Guest Agent Command)}, +{desc, N_(Qemu Guest Agent Command)}, +{NULL, NULL} +}; + +static const vshCmdOptDef opts_qemu_agent_command[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{timeout, VSH_OT_INT, VSH_OFLAG_REQ_OPT, N_(timeout)}, +{cmd, VSH_OT_ARGV, VSH_OFLAG_REQ, N_(command)}, +{NULL, 0, 0, NULL} +}; + +static bool +cmdQemuAgentCommand(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom = NULL; +bool ret = false; +char *guest_agent_cmd = NULL; +char *result = NULL; +int timeout = 0; +unsigned int flags = 0; +const vshCmdOpt *opt = NULL; +virBuffer buf = VIR_BUFFER_INITIALIZER; +bool pad = false; + +if (!vshConnectionUsability(ctl, ctl-conn)) +goto cleanup; + +dom = vshCommandOptDomain(ctl, cmd, NULL); +if (dom == NULL) +goto cleanup; + +while ((opt = vshCommandOptArgv(cmd, opt))) { +if (pad) +virBufferAddChar(buf, ' '); +pad = true; +virBufferAdd(buf, opt-data, -1); +} +if (virBufferError(buf)) { +vshPrint(ctl, %s, _(Failed to collect command)); +goto cleanup; +} +guest_agent_cmd = virBufferContentAndReset(buf); + +if (vshCommandOptInt(cmd, timeout, timeout) 0) { +timeout = 0; +} + +if (virDomainQemuAgentCommand(dom, guest_agent_cmd, result, + timeout, flags) 0) +goto cleanup; + +printf(%s\n, result); + +ret = true; + +cleanup: +VIR_FREE(result); +VIR_FREE(guest_agent_cmd); +if (dom) +virDomainFree(dom); + +return ret; +} +/* * sysinfo command */ static const vshCmdInfo info_sysinfo[] = { @@ -832,6 +900,8 @@ static const vshCmdDef hostAndHypervisorCmds[] = { {qemu-attach, cmdQemuAttach, opts_qemu_attach, info_qemu_attach, 0}, {qemu-monitor-command, cmdQemuMonitorCommand, opts_qemu_monitor_command, info_qemu_monitor_command, 0}, +{qemu-agent-command, cmdQemuAgentCommand, opts_qemu_agent_command, + info_qemu_agent_command, 0}, {sysinfo, cmdSysinfo, NULL, info_sysinfo, 0}, {uri, cmdURI, NULL, info_uri, 0}, {version, cmdVersion, opts_version, info_version, 0}, -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/5] add timeout seconds to qemuAgentSend()
Add @seconds valuable to qemuAgentSend(). It points timeout seconds on @timeout true. If @seconds is 0 on @timeout true, use default timeout value (QEMU_AGENT_WAIT_TIME). If @timeout is false, @seconds is meanless. qemu_agent.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 15af758..7699042 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -837,6 +837,7 @@ void qemuAgentClose(qemuAgentPtr mon) * @mon: Monitor * @msg: Message * @timeout: use timeout? + * @seconds: timeout seconds. if 0 on @timeout true, use default value * * Send @msg to agent @mon. * Wait max QEMU_AGENT_WAIT_TIME for agent @@ -848,7 +849,8 @@ void qemuAgentClose(qemuAgentPtr mon) */ static int qemuAgentSend(qemuAgentPtr mon, qemuAgentMessagePtr msg, - bool timeout) + bool timeout, + int seconds) { int ret = -1; unsigned long long now, then = 0; @@ -864,7 +866,7 @@ static int qemuAgentSend(qemuAgentPtr mon, if (timeout) { if (virTimeMillisNow(now) 0) return -1; -then = now + QEMU_AGENT_WAIT_TIME; +then = now + (seconds == 0 ? QEMU_AGENT_WAIT_TIME : seconds * 1000); } mon-msg = msg; @@ -937,7 +939,7 @@ qemuAgentGuestSync(qemuAgentPtr mon) VIR_DEBUG(Sending guest-sync command with ID: %llu, id); -send_ret = qemuAgentSend(mon, sync_msg, true); +send_ret = qemuAgentSend(mon, sync_msg, true, 0); VIR_DEBUG(qemuAgentSend returned: %d, send_ret); @@ -977,7 +979,8 @@ cleanup: static int qemuAgentCommand(qemuAgentPtr mon, virJSONValuePtr cmd, - virJSONValuePtr *reply) + virJSONValuePtr *reply, + int timeout) { int ret = -1; qemuAgentMessage msg; @@ -1005,7 +1008,7 @@ qemuAgentCommand(qemuAgentPtr mon, VIR_DEBUG(Send command '%s' for write, cmdstr); -ret = qemuAgentSend(mon, msg, false); +ret = qemuAgentSend(mon, msg, (timeout 0 ? true : false), timeout); VIR_DEBUG(Receive command reply ret=%d rxObject=%p, ret, msg.rxObject); @@ -1283,7 +1286,7 @@ int qemuAgentShutdown(qemuAgentPtr mon, return -1; mon-await_event = QEMU_AGENT_EVENT_SHUTDOWN; -ret = qemuAgentCommand(mon, cmd, reply); +ret = qemuAgentCommand(mon, cmd, reply, 0); if (reply ret == 0) ret = qemuAgentCheckError(cmd, reply); @@ -1315,7 +1318,7 @@ int qemuAgentFSFreeze(qemuAgentPtr mon) if (!cmd) return -1; -if (qemuAgentCommand(mon, cmd, reply) 0 || +if (qemuAgentCommand(mon, cmd, reply, 0) 0 || qemuAgentCheckError(cmd, reply) 0) goto cleanup; @@ -1352,7 +1355,7 @@ int qemuAgentFSThaw(qemuAgentPtr mon) if (!cmd) return -1; -if (qemuAgentCommand(mon, cmd, reply) 0 || +if (qemuAgentCommand(mon, cmd, reply, 0) 0 || qemuAgentCheckError(cmd, reply) 0) goto cleanup; @@ -1389,7 +1392,7 @@ qemuAgentSuspend(qemuAgentPtr mon, return -1; mon-await_event = QEMU_AGENT_EVENT_SUSPEND; -ret = qemuAgentCommand(mon, cmd, reply); +ret = qemuAgentCommand(mon, cmd, reply, 0); if (reply ret == 0) ret = qemuAgentCheckError(cmd, reply); -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 0/5] support guest agent general command
Hi, All. I rewrote the patches as Eric suggested. virsh # help qemu-agent-command NAME qemu-agent-command - Qemu Guest Agent Command SYNOPSIS qemu-agent-command domain [--timeout number] {[--cmd] string}... DESCRIPTION Qemu Guest Agent Command OPTIONS [--domain] string domain name, id or uuid --timeout number timeout [--cmd] string command virsh # qemu-agent-command RHEL58_64 '{execute:guest-info}' {return:{version:1.1.50,supported_commands:[{enabled:true,name:guest-network-get-interfaces},{enabled:true,name:guest-suspend-hybrid},{enabled:true,name:guest-suspend-ram},{enabled:true,name:guest-suspend-disk},{enabled:true,name:guest-fsfreeze-thaw},{enabled:true,name:guest-fsfreeze-freeze},{enabled:true,name:guest-fsfreeze-status},{enabled:true,name:guest-file-flush},{enabled:true,name:guest-file-seek},{enabled:true,name:guest-file-write},{enabled:true,name:guest-file-read},{enabled:true,name:guest-file-close},{enabled:true,name:guest-file-open},{enabled:true,name:guest-shutdown},{enabled:true,name:guest-info},{enabled:true,name:guest-ping},{enabled:true,name:guest-sync},{enabled:true,name:guest-sync-delimited}]}} virsh # qemu-agent-command RHEL58_64 '{execute:guest-sync, arguments:{id:123}}' {return:123} -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 4/5] Add virDomainQemuAgentCommand() support function to python module
Add virDomainQemuAgentCommand() support function to python module. generator.py |1 + libvirt-qemu-override-api.xml |8 libvirt-qemu-override.c | 31 +++ 3 files changed, 40 insertions(+) diff --git a/python/generator.py b/python/generator.py index 6559ece..3cec12b 100755 --- a/python/generator.py +++ b/python/generator.py @@ -431,6 +431,7 @@ skip_impl = ( qemu_skip_impl = ( 'virDomainQemuMonitorCommand', +'virDomainQemuAgentCommand', ) diff --git a/python/libvirt-qemu-override-api.xml b/python/libvirt-qemu-override-api.xml index d69acea..37759d0 100644 --- a/python/libvirt-qemu-override-api.xml +++ b/python/libvirt-qemu-override-api.xml @@ -8,5 +8,13 @@ arg name='cmd' type='const char *' info='the command which will be passed to QEMU monitor'/ arg name='flags' type='unsigned int' info='an ORapos;ed set of virDomainQemuMonitorCommandFlags'/ /function + function name='virDomainQemuAgentCommand' file='python-qemu' +infoSend a Guest Agent command to domain/info +return type='str *' info='the command output or None in case of error'/ +arg name='domain' type='virDomainPtr' info='pointer to the domain'/ +arg name='cmd' type='const char *' info='guest agent command on domain'/ +arg name='timeout' type='int' info='timeout seconds'/ +arg name='flags' type='unsigned int' info='execution flags'/ + /function /symbols /api diff --git a/python/libvirt-qemu-override.c b/python/libvirt-qemu-override.c index e532416..195aadc 100644 --- a/python/libvirt-qemu-override.c +++ b/python/libvirt-qemu-override.c @@ -82,6 +82,36 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, return py_retval; } +static PyObject * +libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) +{ +PyObject *py_retval; +char *result = NULL; +virDomainPtr domain; +PyObject *pyobj_domain; +int timeout; +unsigned int flags; +char *cmd; +int c_retval; + +if (!PyArg_ParseTuple(args, (char *)Ozii:virDomainQemuAgentCommand, + pyobj_domain, cmd, timeout, flags)) +return NULL; +domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + +if (domain == NULL) +return VIR_PY_NONE; +LIBVIRT_BEGIN_ALLOW_THREADS; +c_retval = virDomainQemuAgentCommand(domain, cmd, result, timeout, flags); +LIBVIRT_END_ALLOW_THREADS; + +if (c_retval 0) +return VIR_PY_NONE; + +py_retval = PyString_FromString(result); +return py_retval; +} / * * * The registration stuff * @@ -90,6 +120,7 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, static PyMethodDef libvirtQemuMethods[] = { #include libvirt-qemu-export.c {(char *) virDomainQemuMonitorCommand, libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL}, +{(char *) virDomainQemuAgentCommand, libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu_agent: support qemu agent general command
ACK or do I need to re-write ? Regards MATSUDA Daiki On 07/13/2012 08:02 AM, Michal Privoznik wrote: On 13.07.2012 15:41, Eric Blake wrote: On 07/13/2012 06:25 AM, Michal Privoznik wrote: On 09.07.2012 12:54, Michal Privoznik wrote: [I am pasting your patch here again so I can point out some nits] On 06.07.2012 03:29, MATSUDA, Daiki wrote: However, I will hold the push for a while. There is one general problem with this patch. Unlike qemu monitor, guest agent has several commands which don't return any successful message (guest-suspend-* family). with current implementation libvirt takes an event on command as confirmation of success. That is - we block until an event is received. But with this patch, if user will issue such command the whole API would block endlessly. I am not sure how we should fix this. Either we will take the current implementation (what if qemu will ever come with new command which doesn't report successful run?) or we introduce a flag DONT_WAIT_FOR_REPLY (tricky, we want to wait for error response - but what timeout should we choose? moreover, timeouts are bad). Therefore, if anybody has any suggestions I am more than happy to hear them. What about this: by default there will be some reasonable timeout (like 30 seconds) for obtaining a reply from agent. And we will have two flags: 1) DONT_WAIT - which will just write command and don't wait for any reply 2) WAIT_INF - which will block endlessly for a reply. Rather than just 2 flags, can we take an integer timeout parameter? If the parameter is -1, then we don't wait; if the parameter is 0, then we wait forever, otherwise, we wait for the user-specified timeout. Okay, but I think the interpretation of values should be reversed: -1 for wait forever 0 not to wait at all I think it's more mnemonic since -1 is all bits set thus huge number hence evokes infinity. Wait for zero time units means no wait at all. Definitely argues that -1 and 0 should have named aliases. Or even use the NULL-ness of result to determine whether to wait: /** * virDomainQemuAgentCommand: * * Issue @cmd to the guest agent running in @domain. * If @result is NULL, then don't wait for a result (and @timeout * must be 0). Otherwise, wait for @timeout seconds for a * successful result to be populated into *@result, with * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK (-1) meaning to block * forever waiting for a result. */ int virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd, char **result, unsigned int timeout, unsigned int flags); And I still stand by my earlier review comment that this needs to be split into multiple patches (introduce public API separate from the qemu-specific implementation of that API, even if the API is only usable by qemu). Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] qemu_agent: support qemu agent general command
Hi, All. Thank you for many comments. And I extremely apologize not to use git... My company's network closes the almost port and only http via proxy and simple mail are available. The attached patch is reflected all comments. Especially, diff -uNrp libvirt-0.9.13.orig/src/driver.h libvirt-0.9.13/src/driver.h --- libvirt-0.9.13.orig/src/driver.h 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/src/driver.h2012-07-02 10:02:54.405454285 +0900 @@ -860,6 +860,10 @@ typedef char * const char *uri, unsigned int flags); +typedef int +(*virDrvDomainGuestAgentCommand)(virDomainPtr domain, const char *cmd, + char **result, unsigned int flags); + /** * _virDriver: * @@ -1041,6 +1045,7 @@ struct _virDriver { virDrvDomainGetDiskErrors domainGetDiskErrors; virDrvDomainSetMetadata domainSetMetadata; virDrvDomainGetMetadata domainGetMetadata; +virDrvDomainGuestAgentCommand qemuDomainGuestAgentCommand; }; I'd move these two as close as possible to virDrvDomainQemuMonitorCommand so we have similar commands grouped. I moved virDrvDomainQemuMonitorCommand to virDrvDomainQemuSupportCommand to close two functions. In addition, diff -uNrp libvirt-0.9.13.orig/src/qemu/qemu_agent.c libvirt-0.9.13/src/qemu/qemu_agent.c --- libvirt-0.9.13.orig/src/qemu/qemu_agent.c 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/src/qemu/qemu_agent.c 2012-07-02 10:02:54.408488163 +0900 @@ -1410,3 +1410,29 @@ qemuAgentSuspend(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +int qemuAgentGuestAgentCommand(qemuAgentPtr mon, + const char *cmd, + char **result) +{ +int ret = -1; +virJSONValuePtr jcmd; +virJSONValuePtr reply = NULL; + +jcmd = qemuAgentMakeCommand(cmd, NULL); +if (!jcmd) +return ret; This is confusing. In case of qemu-monitor-command we require user to pass whole command string: {'execute':'some-dummy-command'} which is correct as we don't lock them in {'execute':'%s'} scheme. Remember, we want them to use commands/features not yet exposed by libvirt. So if qemu will ever come up with different command scheme this API will remain broken. In addition - and this is even more serious - there is no way of specifying arguments to a command, e.g. guest-sync take an integer: {'execute':'guest-sync', 'arguments':{'id':123}} Therefore I think we need to drop qemuAgentMakeCommand() here and require users to do the very same here as they do in qemu-monitor-command. I prefer to the type of 'virsh qemu-agent-command guest-info', bacause it is user friendly. But I understood the problem and fixed. Regards MATSUDA Daiki $ diffstat libvirt-0.9.13_qemu_agent_command3.patch daemon/remote.c | 36 + docs/hvsupport.pl|1 include/libvirt/libvirt-qemu.h |3 + python/generator.py |1 python/libvirt-qemu-override-api.xml |7 +++ python/libvirt-qemu-override.c | 31 ++ src/driver.h |5 +- src/libvirt-qemu.c | 49 +++ src/libvirt_qemu.syms|5 ++ src/qemu/qemu_agent.c| 26 src/qemu/qemu_agent.h|4 + src/qemu/qemu_driver.c | 73 +++ src/qemu_protocol-structs|9 src/remote/qemu_protocol.x | 13 +- src/remote/remote_driver.c | 39 ++ tools/virsh.c| 64 ++ 16 files changed, 363 insertions(+), 3 deletions(-) virsh # qemu-agent-command RHEL58_64 '{execute:guest-info}' {return:{version:1.1.50,supported_commands:[{enabled:true,name:guest-network-get-interfaces},{enabled:true,name:guest-suspend-hybrid},{enabled:true,name:guest-suspend-ram},{enabled:true,name:guest-suspend-disk},{enabled:true,name:guest-fsfreeze-thaw},{enabled:true,name:guest-fsfreeze-freeze},{enabled:true,name:guest-fsfreeze-status},{enabled:true,name:guest-file-flush},{enabled:true,name:guest-file-seek},{enabled:true,name:guest-file-write},{enabled:true,name:guest-file-read},{enabled:true,name:guest-file-close},{enabled:true,name:guest-file-open},{enabled:true,name:guest-shutdown},{enabled:true,name:guest-info},{enabled:true,name:guest-ping},{enabled:true,name:guest-sync},{enabled:true,name:guest-sync-delimited}]}} virsh # qemu-agent-command RHEL58_64 '{execute:guest-sync, arguments:{id:123}}' {return:123} diff -uNrp libvirt-0.9.13.orig/daemon/remote.c libvirt-0.9.13/daemon/remote.c --- libvirt-0.9.13.orig/daemon/remote.c 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13
Re: [libvirt] [PATCH] qemu_agent: support guest-info command
Mr. Daniel. I rewrote the patch for libvirt-0.9.13 to move some codes to libvirt-qemu as you suggested. But I am sorry for unusing git, because my joining company is very elegant for network security. So, I have an only way via http to get libvirt's source code... Regards MATSUDA Daiki virsh # help QEMU Guest Agent (help keyword 'guestagent'): qemu-agent-command Qemu Guest Agent Command Virsh itself (help keyword 'virsh'): cd change the current directory echo echo arguments exit quit this interactive terminal help print help pwdprint the current directory quit quit this interactive terminal virsh # help qemu-agent-command NAME qemu-agent-command - Qemu Guest Agent Command SYNOPSIS qemu-agent-command domain {[--cmd] string}... DESCRIPTION Qemu Guest Agent Command OPTIONS [--domain] string domain name, id or uuid [--cmd] string command virsh # qemu-agent-command RHEL58_64 guest-info {return:{version:1.1.50,supported_commands:[{enabled:true,name:guest-network-get-interfaces},{enabled:true,name:guest-suspend-hybrid},{enabled:true,name:guest-suspend-ram},{enabled:true,name:guest-suspend-disk},{enabled:true,name:guest-fsfreeze-thaw},{enabled:true,name:guest-fsfreeze-freeze},{enabled:true,name:guest-fsfreeze-status},{enabled:true,name:guest-file-flush},{enabled:true,name:guest-file-seek},{enabled:true,name:guest-file-write},{enabled:true,name:guest-file-read},{enabled:true,name:guest-file-close},{enabled:true,name:guest-file-open},{enabled:true,name:guest-shutdown},{enabled:true,name:guest-info},{enabled:true,name:guest-ping},{enabled:true,name:guest-sync},{enabled:true,name:guest-sync-delimited}]}} On Fri, Jun 29, 2012 at 01:58:05PM +0900, MATSUDA, Daiki wrote: diff -uNrp libvirt-0.9.13.orig/daemon/remote.c libvirt-0.9.13/daemon/remote.c --- libvirt-0.9.13.orig/daemon/remote.c 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/daemon/remote.c 2012-06-29 12:50:03.752806682 +0900 @@ -3923,6 +3923,42 @@ cleanup: return rv; } + +static int +remoteDispatchDomainQemuAgentCommand(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_qemu_agent_command_args *args, + remote_domain_qemu_agent_command_ret *ret) +{ +virDomainPtr dom = NULL; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; + +if (virDomainQemuAgentCommand(dom, args-cmd, ret-result, args-flags) 0) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(Guest Agent Error)); +goto cleanup; +} + +rv = 0; +cleanup: +if (rv 0) +virNetMessageSaveError(rerr); +if (dom) +virDomainFree(dom); +return rv; +} + /*- Helpers. -*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff -uNrp libvirt-0.9.13.orig/daemon/remote_dispatch.h libvirt-0.9.13/daemon/remote_dispatch.h --- libvirt-0.9.13.orig/daemon/remote_dispatch.h2012-06-25 19:48:08.0 +0900 +++ libvirt-0.9.13/daemon/remote_dispatch.h 2012-06-29 10:21:21.460454579 +0900 @@ -12889,6 +12889,28 @@ static int remoteDispatchSupportsFeature +static int remoteDispatchDomainQemuAgentCommand( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +remote_domain_qemu_agent_command_args *args, +remote_domain_qemu_agent_command_ret *ret); +static int remoteDispatchDomainQemuAgentCommandHelper( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +void *args, +void *ret) +{ + VIR_DEBUG(server=%p client=%p msg=%p rerr=%p args=%p ret=%p, server, client, msg, rerr, args, ret); + return remoteDispatchDomainQemuAgentCommand(server, client, msg, rerr, args, ret); +} +/* remoteDispatchDomainQemuAgentCommand body has to be implemented manually */ + + + virNetServerProgramProc remoteProcs[] = { { /* Unused 0 */ NULL, @@ -15374,5 +15396,14 @@ virNetServerProgramProc remoteProcs[] = true, 1 }, +{ /* Method DomainQemuAgentCommand = 276 */ + remoteDispatchDomainQemuAgentCommandHelper, + sizeof(remote_domain_qemu_agent_command_args), + (xdrproc_t)xdr_remote_qemu_agent_command_args, + sizeof
Re: [libvirt] [PATCH] qemu_agent: support guest-info command
By the way, I am trying to re-write to move some functions to libvirt-qemu as you adviced. But the result is not good not to print Guest Agent's command response... In addition, VIR_DEBUG() in src/libvirt-qemu.c also does not output to log file. Though I minded much before, I think that 'qemu-monitor-command' does not work correctly. Does anyone can get good result with its command ? Regards MATSUDA Daiki On Fri, Jun 29, 2012 at 01:58:05PM +0900, MATSUDA, Daiki wrote: diff -uNrp libvirt-0.9.13.orig/daemon/remote.c libvirt-0.9.13/daemon/remote.c --- libvirt-0.9.13.orig/daemon/remote.c 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/daemon/remote.c 2012-06-29 12:50:03.752806682 +0900 @@ -3923,6 +3923,42 @@ cleanup: return rv; } + +static int +remoteDispatchDomainQemuAgentCommand(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_qemu_agent_command_args *args, + remote_domain_qemu_agent_command_ret *ret) +{ +virDomainPtr dom = NULL; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; + +if (virDomainQemuAgentCommand(dom, args-cmd, ret-result, args-flags) 0) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(Guest Agent Error)); +goto cleanup; +} + +rv = 0; +cleanup: +if (rv 0) +virNetMessageSaveError(rerr); +if (dom) +virDomainFree(dom); +return rv; +} + /*- Helpers. -*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff -uNrp libvirt-0.9.13.orig/daemon/remote_dispatch.h libvirt-0.9.13/daemon/remote_dispatch.h --- libvirt-0.9.13.orig/daemon/remote_dispatch.h2012-06-25 19:48:08.0 +0900 +++ libvirt-0.9.13/daemon/remote_dispatch.h 2012-06-29 10:21:21.460454579 +0900 @@ -12889,6 +12889,28 @@ static int remoteDispatchSupportsFeature +static int remoteDispatchDomainQemuAgentCommand( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +remote_domain_qemu_agent_command_args *args, +remote_domain_qemu_agent_command_ret *ret); +static int remoteDispatchDomainQemuAgentCommandHelper( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +void *args, +void *ret) +{ + VIR_DEBUG(server=%p client=%p msg=%p rerr=%p args=%p ret=%p, server, client, msg, rerr, args, ret); + return remoteDispatchDomainQemuAgentCommand(server, client, msg, rerr, args, ret); +} +/* remoteDispatchDomainQemuAgentCommand body has to be implemented manually */ + + + virNetServerProgramProc remoteProcs[] = { { /* Unused 0 */ NULL, @@ -15374,5 +15396,14 @@ virNetServerProgramProc remoteProcs[] = true, 1 }, +{ /* Method DomainQemuAgentCommand = 276 */ + remoteDispatchDomainQemuAgentCommandHelper, + sizeof(remote_domain_qemu_agent_command_args), + (xdrproc_t)xdr_remote_qemu_agent_command_args, + sizeof(remote_domain_qemu_agent_command_ret), + (xdrproc_t)remote_domain_qemu_agent_command_ret, + true, + 0 +}, }; size_t remoteNProcs = ARRAY_CARDINALITY(remoteProcs); This is an auto-generated file. Instead of doing a diff against two unpacked tar.gz archives, developer against a git checkout, and use GIT to produce the patch without the auto-generated cruft. diff -uNrp libvirt-0.9.13.orig/include/libvirt/libvirt.h.in libvirt-0.9.13/include/libvirt/libvirt.h.in --- libvirt-0.9.13.orig/include/libvirt/libvirt.h.in2012-06-25 21:42:32.0 +0900 +++ libvirt-0.9.13/include/libvirt/libvirt.h.in 2012-06-29 11:22:38.113455058 +0900 @@ -4132,6 +4132,9 @@ typedef struct _virTypedParameter virMem */ typedef virMemoryParameter *virMemoryParameterPtr; +int virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd, + char **result, unsigned int flags); + #ifdef __cplusplus } #endif This should be in libvirt-qemu.h diff -uNrp libvirt-0.9.13.orig/src/libvirt.c libvirt-0.9.13/src/libvirt.c --- libvirt-0.9.13.orig/src/libvirt.c 2012-06-28 12:05:04.0 +0900 +++ libvirt-0.9.13/src/libvirt.c2012-06-29 12:51:51.336454508 +0900 @@ -18973,3 +18973,44 @@ error: virDispatchError(dom-conn); return -1; } + +/** + * virDomainQemuAgentCommand: + * @domain: a domain object + * @cmd: execution command on domain's guest agent + * @result: returning strings + * @flags: execution flags
Re: [libvirt] [PATCH] qemu_agent: support guest-info command
Daniel Thank you for your comment. And I rewrite the patch with int virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd, char **result, unsigned int flags); that you suggested. The attached patch is against libvirt-0.9.13-rc2 virsh # qemu-agent-command RHEL58_64 guest-info {return:{version:1.1.50,supported_commands:[{enabled:true,name:guest-network-get-interfaces},{enabled:true,name:guest-suspend-hybrid},{enabled:true,name:guest-suspend-ram},{enabled:true,name:guest-suspend-disk},{enabled:true,name:guest-fsfreeze-thaw},{enabled:true,name:guest-fsfreeze-freeze},{enabled:true,name:guest-fsfreeze-status},{enabled:true,name:guest-file-flush},{enabled:true,name:guest-file-seek},{enabled:true,name:guest-file-write},{enabled:true,name:guest-file-read},{enabled:true,name:guest-file-close},{enabled:true,name:guest-file-open},{enabled:true,name:guest-shutdown},{enabled:true,name:guest-info},{enabled:true,name:guest-ping},{enabled:true,name:guest-sync},{enabled:true,name:guest-sync-delimited}]}} On Tue, Jun 26, 2012 at 12:42:03PM +0900, MATSUDA, Daiki wrote: Currently, libvirt qemu agent supports some QEMU Guest Agent's commands or use them. But they are not adapted to communication test to the Domain OS. So, QEMU Guest Agent provide 'guest-info' command to display its version and their commands. And I wrote the codes for supporting it. virsh # guest-agent-info RHEL62_32 Version: 1.1.0 Commands: guest-network-get-interfaces guest-suspend-hybrid guest-suspend-ram guest-suspend-disk guest-fsfreeze-thaw guest-fsfreeze-freeze guest-fsfreeze-status guest-file-flush guest-file-seek guest-file-write guest-file-read guest-file-close guest-file-open guest-shutdown guest-info guest-ping guest-sync guest-sync-delimited I don't really think that this kind of API is relevant for the libvirt public API. Individual agent commands are wired up to specific libvirt public APIs as required. There is no compelling reason why an end user needs to know what agent commands are present. I would, however, support the introduction of an API int virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd, char **result, unsigned int flags); and virsh command 'qemu-agent-command' as part of libvirt-qemu.h and libvirt-qemu.so. Basically an equivalent of the existing QEMU specific API virDomainQemuMonitorCommand(), but talking to the agent instead of the monitor Regards, Daniel diff -uNrp libvirt-0.9.13.orig/daemon/remote.c libvirt-0.9.13/daemon/remote.c --- libvirt-0.9.13.orig/daemon/remote.c 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/daemon/remote.c 2012-06-29 12:50:03.752806682 +0900 @@ -3923,6 +3923,42 @@ cleanup: return rv; } + +static int +remoteDispatchDomainQemuAgentCommand(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_qemu_agent_command_args *args, + remote_domain_qemu_agent_command_ret *ret) +{ +virDomainPtr dom = NULL; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; + +if (virDomainQemuAgentCommand(dom, args-cmd, ret-result, args-flags) 0) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(Guest Agent Error)); +goto cleanup; +} + +rv = 0; +cleanup: +if (rv 0) +virNetMessageSaveError(rerr); +if (dom) +virDomainFree(dom); +return rv; +} + /*- Helpers. -*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff -uNrp libvirt-0.9.13.orig/daemon/remote_dispatch.h libvirt-0.9.13/daemon/remote_dispatch.h --- libvirt-0.9.13.orig/daemon/remote_dispatch.h2012-06-25 19:48:08.0 +0900 +++ libvirt-0.9.13/daemon/remote_dispatch.h 2012-06-29 10:21:21.460454579 +0900 @@ -12889,6 +12889,28 @@ static int remoteDispatchSupportsFeature +static int remoteDispatchDomainQemuAgentCommand( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +remote_domain_qemu_agent_command_args *args, +remote_domain_qemu_agent_command_ret *ret); +static int remoteDispatchDomainQemuAgentCommandHelper( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr
[libvirt] [PATCH] qemu_agent: support guest-info command
Currently, libvirt qemu agent supports some QEMU Guest Agent's commands or use them. But they are not adapted to communication test to the Domain OS. So, QEMU Guest Agent provide 'guest-info' command to display its version and their commands. And I wrote the codes for supporting it. virsh # guest-agent-info RHEL62_32 Version: 1.1.0 Commands: guest-network-get-interfaces guest-suspend-hybrid guest-suspend-ram guest-suspend-disk guest-fsfreeze-thaw guest-fsfreeze-freeze guest-fsfreeze-status guest-file-flush guest-file-seek guest-file-write guest-file-read guest-file-close guest-file-open guest-shutdown guest-info guest-ping guest-sync guest-sync-delimited I am sorry that attached patch is against libvirt-0.9.13-rc1, because my network environment can not access via git and header code is not built with the problem gnulib... Regards MATSUDA Daiki diff -uNrp libvirt-0.9.13.orig/daemon/remote.c libvirt-0.9.13/daemon/remote.c --- libvirt-0.9.13.orig/daemon/remote.c 2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/daemon/remote.c 2012-06-26 11:34:02.058455043 +0900 @@ -3923,6 +3923,46 @@ cleanup: return rv; } +static int remoteDispatchDomainGuestAgentInfo(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_domain_guest_agent_info_args *args, + remote_domain_guest_agent_info_ret *ret) +{ +virDomainPtr dom = NULL; +int rv = -1; +struct daemonClientPrivate *priv = +virNetServerClientGetPrivateData(client); + +if (!priv-conn) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(connection not open)); +goto cleanup; +} + +if (!(dom = get_nonnull_domain(priv-conn, args-dom))) +goto cleanup; + +ret-buffer.buffer_len = REMOTE_DOMAIN_GA_INFO_BUFFER_MAX; +if (VIR_ALLOC_N (ret-buffer.buffer_val, REMOTE_DOMAIN_GA_INFO_BUFFER_MAX) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virDomainGuestAgentInfo(dom, (ret-buffer.buffer_val)) 0) { +virNetError(VIR_ERR_INTERNAL_ERROR, %s, _(Guest Agent Error)); +goto cleanup; +} + +rv = 0; +cleanup: +if (rv 0) +virNetMessageSaveError(rerr); +if (dom) +virDomainFree(dom); +return rv; +} + /*- Helpers. -*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff -uNrp libvirt-0.9.13.orig/daemon/remote_dispatch.h libvirt-0.9.13/daemon/remote_dispatch.h --- libvirt-0.9.13.orig/daemon/remote_dispatch.h2012-06-25 19:48:08.0 +0900 +++ libvirt-0.9.13/daemon/remote_dispatch.h 2012-06-26 11:36:45.846454615 +0900 @@ -12889,6 +12889,28 @@ static int remoteDispatchSupportsFeature +static int remoteDispatchDomainGuestAgentInfo( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +remote_domain_guest_agent_info_args *args, +remote_domain_guest_agent_info_ret *ret); +static int remoteDispatchDomainGuestAgentInfoHelper( +virNetServerPtr server, +virNetServerClientPtr client, +virNetMessagePtr msg, +virNetMessageErrorPtr rerr, +void *args, +void *ret) +{ + VIR_DEBUG(server=%p client=%p msg=%p rerr=%p args=%p ret=%p, server, client, msg, rerr, args, ret); + return remoteDispatchDomainGuestAgentInfo(server, client, msg, rerr, args, ret); +} +/* remoteDispatchDomainGuestAgentInfo body has to be implemented manually */ + + + virNetServerProgramProc remoteProcs[] = { { /* Unused 0 */ NULL, @@ -15374,5 +15396,14 @@ virNetServerProgramProc remoteProcs[] = true, 1 }, +{ /* Method DomainGuestAgentInfo = 276 */ + remoteDispatchDomainGuestAgentInfoHelper, + sizeof(remote_domain_guest_agent_info_args), + (xdrproc_t)xdr_remote_guest_agent_info_args, + sizeof(remote_domain_guest_agent_info_ret), + (xdrproc_t)remote_domain_guest_agent_info_ret, + true, + 0 +}, }; size_t remoteNProcs = ARRAY_CARDINALITY(remoteProcs); diff -uNrp libvirt-0.9.13.orig/include/libvirt/libvirt.h.in libvirt-0.9.13/include/libvirt/libvirt.h.in --- libvirt-0.9.13.orig/include/libvirt/libvirt.h.in2012-06-25 16:06:18.0 +0900 +++ libvirt-0.9.13/include/libvirt/libvirt.h.in 2012-06-26 11:38:08.694455103 +0900 @@ -4128,6 +4128,11 @@ typedef struct _virTypedParameter virMem */ typedef virMemoryParameter *virMemoryParameterPtr; +/** + * Guest Agent Code: + */ +int virDomainGuestAgentInfo(virDomainPtr domain, char **buffer); + #ifdef __cplusplus } #endif diff -uNrp libvirt-0.9.13.orig/python
[libvirt] [PATCH] UML: may be typo
I found typo in UML driver. MATSUDA Daiki --- libvirt-0.9.11/src/uml/uml_driver.c.orig2012-04-09 11:56:47.105695476 +0900 +++ libvirt-0.9.11/src/uml/uml_driver.c 2012-04-09 11:56:56.653820665 +0900 @@ -249,7 +249,7 @@ umlIdentifyChrPTY(struct uml_driver *dri { int i; -for (i = 0 ; i dom-def-nserials; i++) +for (i = 0 ; i dom-def-nconsoles; i++) if (dom-def-consoles[i]-source.type == VIR_DOMAIN_CHR_TYPE_PTY) if (umlIdentifyOneChrPTY(driver, dom, dom-def-consoles[i], con) 0) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2 1/3] qemu_agent: Create file system freeze and thaw functions
I am happy that you provide the patches. These functions simply issue command to guest agent which should freeze or unfreeze all file systems within guest. --- src/qemu/qemu_agent.c | 74 + src/qemu/qemu_agent.h |3 ++ 2 files changed, 77 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 6a7c7b3..9df5546 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -1110,3 +1110,77 @@ int qemuAgentShutdown(qemuAgentPtr mon, virJSONValueFree(reply); return ret; } + +/* + * qemuAgentFSFreeze: + * @mon: Agent + * + * Issue guest-fsfreeze-freeze command to guest agent, + * which freezes all mounted file systems and returns + * number of frozen file systems on success. + * + * Returns: number of file system frozen on success, + * -1 on error. + */ +int qemuAgentFSFreeze(qemuAgentPtr mon) +{ +int ret = -1; +virJSONValuePtr cmd; +virJSONValuePtr reply = NULL; + +cmd = qemuAgentMakeCommand(guest-fsfreeze-freeze, NULL); + +if (!cmd) +return -1; + +if (qemuAgentCommand(mon, cmd,reply) 0 || +qemuAgentCheckError(cmd, reply) 0) +goto cleanup; + +if (virJSONValueObjectGetNumberInt(reply, return,ret) 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, %s, +_(malformed return value)); +} + +cleanup: +virJSONValueFree(cmd); +virJSONValueFree(reply); +return ret; +} + +/* + * qemuAgentFSThaw: + * @mon: Agent + * + * Issue guest-fsfreeze-thaw command to guest agent, + * which unfreezes all mounted file systems and returns + * number of thawed file systems on success. + * + * Returns: number of file system thawed on success, + * -1 on error. + */ +int qemuAgentFSThaw(qemuAgentPtr mon) +{ +int ret = -1; +virJSONValuePtr cmd; +virJSONValuePtr reply = NULL; + +cmd = qemuAgentMakeCommand(guest-fsfreeze-thaw, NULL); + +if (!cmd) +return -1; + +if (qemuAgentCommand(mon, cmd,reply) 0 || +qemuAgentCheckError(cmd, reply) 0) +goto cleanup; + +if (virJSONValueObjectGetNumberInt(reply, return,ret) 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, %s, +_(malformed return value)); +} + +cleanup: +virJSONValueFree(cmd); +virJSONValueFree(reply); +return ret; +} But qemuAgentFSFreeze() and qemuAgentFSThaw() are almost same. In addition, qemu guest agent provides status option for FS Freezer. So, could you change to following? VIR_ENUM_DECL(qemuAgentFSFreezeCtlMode); VIR_ENUM_IMPL(qemuAgentFSFreezeCtlMode, QEMU_AGENT_FSFREEZE_LAST, guest-fsfreeze-freeze, guest-fsfreeze-thaw, guest-fsfreeze-status); int qemuAgentFSFreezeCtl(qemuAGentPtr mon, qemuAgentFSFreezeCtlMode mode){ ... cmd = qemuAgentMakeCommand(qemuAgentFSFreezeCtlModeToString(mode), NULL); ... diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 93c2ae7..df59ef7 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -66,4 +66,7 @@ typedef enum { int qemuAgentShutdown(qemuAgentPtr mon, qemuAgentShutdownMode mode); +int qemuAgentFSFreeze(qemuAgentPtr mon); +int qemuAgentFSThaw(qemuAgentPtr mon); + #endif /* __QEMU_AGENT_H__ */ Similarly int qemuAgentFSFreezeCtl(qemuAgentPtr mon, qemuAgentFSFreezeCtlMode mode); -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] virtio console: name=foo is not supported
(2011/12/13 13:02), MATSUDA, Daiki wrote: (2011/12/12 22:58), Daniel P. Berrange wrote: On Mon, Dec 12, 2011 at 10:18:23AM +0900, MATSUDA, Daiki wrote: In addition, the QEMU guest agent requires specified socket. Virt IO Console, too. But unfortunately libvirt does not support to xml tags to give socket name options to QEMU for the QEMU guest agent and Virt IO Console. Err, yes we do. channel type='unix' source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/ target type='virtio' name='org.qemu.guest_agent.0'/ /channel Yes, I confirmed that it can create the socket for guest agent and communicate to guest. Or for the console console type='unix' source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.console'/ target type='virtio'/ /channel though you really want to use type=pty for consoles, so that 'virsh console' works correctly. Daniel But It is not enough. Because I use the socket for VirtIO console, i.e. gives the option '-device virtconsole,chardev=...,name=foo' for qemu. And I read the source code, but found funny... In src/conf/domain_conf.h, struct _virDomainChrDef is struct _virDomainChrDef { ... union { int port; /* parallel, serial, console */ virSocketAddrPtr addr; /* guestfwd */ char *name; /* virtio */ } target; ... It is written that virtio must use char *name. But in docs/schemas/domaincommon.rng and others, VirtIO Console use only int port. Thoug I do not understand that which should be used, I attaches the patch for using *name. Neither is really relevant for virtio-console, it just provides one or more interactive console for admins. The name is only relevant when coming to create virtio serial channels for non-interactive use. eg thechannel elements. Daniel My simple requirement is to give qemu the option such as -device virtio-serial \ -chardev socket,path=/tmp/foo,server,nowait,id=foo \ -device virtconsole,chardev=foo,name=org.fedoraproject.console.foo (e.g. http://fedoraproject.org/wiki/Features/VirtioSerial it has a little mistake not virtioconsole but virtconsole.) But current libvirt source code does not accept name=... with virtconsole. Because 'virtconsole' is only added on qemuBuildVirtioSerialPortDevStr() in src/qemu/qemu_command.c when dev-deviceType is VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE and 'name=' is only added on some function when dev-deviceType is VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL. Similarly it is impossible to use channel instead of console for virtconsole because deviceType is set as VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL. So, if it is possible to take 2 options port and name for console virtio, could you modify from union to struct on struct _vifDomainChrDef in src/conf/domain_conf.h ? MATSUDA Daiki -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list I have modified the patch to change from union to struct for struct _vifDomainChrDef. At least, port and name can exist togethter. MATSUDA Daiki diff -uNrp libvirt-0.9.8.orig/docs/schemas/domaincommon.rng libvirt-0.9.8/docs/schemas/domaincommon.rng --- libvirt-0.9.8.orig/docs/schemas/domaincommon.rng 2011-12-08 11:29:49.0 +0900 +++ libvirt-0.9.8/docs/schemas/domaincommon.rng 2011-12-15 08:51:27.829971955 +0900 @@ -1814,6 +1814,9 @@ optional attribute name=port/ /optional +optional + attribute name=name/ +/optional /interleave /element /define diff -uNrp libvirt-0.9.8.orig/src/conf/domain_conf.c libvirt-0.9.8/src/conf/domain_conf.c --- libvirt-0.9.8.orig/src/conf/domain_conf.c 2011-12-08 11:29:49.0 +0900 +++ libvirt-0.9.8/src/conf/domain_conf.c2011-12-15 08:51:27.839971932 +0900 @@ -1156,22 +1156,10 @@ void virDomainChrDefFree(virDomainChrDef if (!def) return; -switch (def-deviceType) { -case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: -switch (def-targetType) { -case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: -VIR_FREE(def-target.addr); -break; - -case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO: -VIR_FREE(def-target.name); -break; -} -break; - -default: -break; -} +if (def-target.addr) +VIR_FREE(def-target.addr); +if (def-target.name) +VIR_FREE(def-target.name); virDomainChrSourceDefClear(def-source); virDomainDeviceInfoClear(def-info); @@ -3969,6 +3957,8 @@ virDomainChrDefParseTargetXML(virCapsPtr break; default: +def-target.name = virXMLPropString(cur, name); + portStr = virXMLPropString(cur, port); if (portStr == NULL) { /* Set to negative value to indicate we should set it later */ @@ -3983,6 +3973,7 @@ virDomainChrDefParseTargetXML(virCapsPtr goto error; } def-target.port = port; + break; } @@ -10406,10 +10397,14 @@ virDomainChrDefFormat(virBufferPtr buf
Re: [libvirt] virtio console: name=foo is not supported
(2011/12/12 22:58), Daniel P. Berrange wrote: On Mon, Dec 12, 2011 at 10:18:23AM +0900, MATSUDA, Daiki wrote: In addition, the QEMU guest agent requires specified socket. Virt IO Console, too. But unfortunately libvirt does not support to xml tags to give socket name options to QEMU for the QEMU guest agent and Virt IO Console. Err, yes we do. channel type='unix' source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/ target type='virtio' name='org.qemu.guest_agent.0'/ /channel Yes, I confirmed that it can create the socket for guest agent and communicate to guest. Or for the console console type='unix' source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.console'/ target type='virtio'/ /channel though you really want to use type=pty for consoles, so that 'virsh console' works correctly. Daniel But It is not enough. Because I use the socket for VirtIO console, i.e. gives the option '-device virtconsole,chardev=...,name=foo' for qemu. And I read the source code, but found funny... In src/conf/domain_conf.h, struct _virDomainChrDef is struct _virDomainChrDef { ... union { int port; /* parallel, serial, console */ virSocketAddrPtr addr; /* guestfwd */ char *name; /* virtio */ } target; ... It is written that virtio must use char *name. But in docs/schemas/domaincommon.rng and others, VirtIO Console use only int port. Thoug I do not understand that which should be used, I attaches the patch for using *name. Neither is really relevant for virtio-console, it just provides one or more interactive console for admins. The name is only relevant when coming to create virtio serial channels for non-interactive use. eg thechannel elements. Daniel My simple requirement is to give qemu the option such as -device virtio-serial \ -chardev socket,path=/tmp/foo,server,nowait,id=foo \ -device virtconsole,chardev=foo,name=org.fedoraproject.console.foo (e.g. http://fedoraproject.org/wiki/Features/VirtioSerial it has a little mistake not virtioconsole but virtconsole.) But current libvirt source code does not accept name=... with virtconsole. Because 'virtconsole' is only added on qemuBuildVirtioSerialPortDevStr() in src/qemu/qemu_command.c when dev-deviceType is VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE and 'name=' is only added on some function when dev-deviceType is VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL. Similarly it is impossible to use channel instead of console for virtconsole because deviceType is set as VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL. So, if it is possible to take 2 options port and name for console virtio, could you modify from union to struct on struct _vifDomainChrDef in src/conf/domain_conf.h ? MATSUDA Daiki -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] virtio console: name=foo is not supported
In addition, the QEMU guest agent requires specified socket. Virt IO Console, too. But unfortunately libvirt does not support to xml tags to give socket name options to QEMU for the QEMU guest agent and Virt IO Console. Err, yes we do. channel type='unix' source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/ target type='virtio' name='org.qemu.guest_agent.0'/ /channel Yes, I confirmed that it can create the socket for guest agent and communicate to guest. Or for the console console type='unix' source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.console'/ target type='virtio'/ /channel though you really want to use type=pty for consoles, so that 'virsh console' works correctly. Daniel But It is not enough. Because I use the socket for VirtIO console, i.e. gives the option '-device virtconsole,chardev=...,name=foo' for qemu. And I read the source code, but found funny... In src/conf/domain_conf.h, struct _virDomainChrDef is struct _virDomainChrDef { ... union { int port; /* parallel, serial, console */ virSocketAddrPtr addr; /* guestfwd */ char *name; /* virtio */ } target; ... It is written that virtio must use char *name. But in docs/schemas/domaincommon.rng and others, VirtIO Console use only int port. Thoug I do not understand that which should be used, I attaches the patch for using *name. P.S. I can not use GIT, because live in restricted network. MATSUDA Daiki diff -uNrp libvirt-0.9.8.orig/docs/schemas/domaincommon.rng libvirt-0.9.8/docs/schemas/domaincommon.rng --- libvirt-0.9.8.orig/docs/schemas/domaincommon.rng2011-12-08 11:29:49.0 +0900 +++ libvirt-0.9.8/docs/schemas/domaincommon.rng 2011-12-12 07:54:30.939996765 +0900 @@ -1800,22 +1800,26 @@ valuexen/value valueserial/value valueuml/value -valuevirtio/value /choice /attribute /define define name=qemucdevTgtDef -element name=target - interleave -optional - ref name=qemucdevConsoleTgtType/ -/optional -optional - attribute name=port/ -/optional - /interleave -/element +choice + element name=target +interleave + optional +ref name=qemucdevConsoleTgtType/ + /optional + optional +attribute name=port/ + /optional +/interleave + /element + choice +ref name=virtioTarget/ + /choice +/choice /define define name=qemucdevSrcTypeChoice diff -uNrp libvirt-0.9.8.orig/src/conf/domain_conf.c libvirt-0.9.8/src/conf/domain_conf.c --- libvirt-0.9.8.orig/src/conf/domain_conf.c 2011-12-08 11:29:49.0 +0900 +++ libvirt-0.9.8/src/conf/domain_conf.c2011-12-12 08:13:06.958096724 +0900 @@ -3969,6 +3969,11 @@ virDomainChrDefParseTargetXML(virCapsPtr break; default: +if (def-targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO +def-deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE) { +def-target.name = virXMLPropString(cur, name); +break; +} portStr = virXMLPropString(cur, port); if (portStr == NULL) { /* Set to negative value to indicate we should set it later */ @@ -7573,7 +7578,12 @@ static virDomainDefPtr virDomainDefParse } } -chr-target.port = i; +/* + * target.port is not accepted for virtio + * See domain_conf.h for struct _virDomainChrDef + */ +if (chr-targetType != VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) +chr-target.port = i; def-consoles[def-nconsoles++] = chr; } @@ -10406,10 +10416,15 @@ virDomainChrDefFormat(virBufferPtr buf, case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE: virBufferAsprintf(buf, -target type='%s' port='%d'/\n, +target type='%s', virDomainChrTargetTypeToString(def-deviceType, - def-targetType), - def-target.port); + def-targetType)); +if (def-targetType != VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) +virBufferAsprintf(buf, port='%d'/\n, def-target.port); +else if (def-target.name) +virBufferAsprintf(buf, name='%s'/\n, def-target.name); +else +virBufferAsprintf(buf, /\n); break; default: diff -uNrp libvirt-0.9.8.orig/src/qemu/qemu_command.c libvirt-0.9.8/src/qemu/qemu_command.c --- libvirt-0.9.8.orig/src/qemu/qemu_command.c 2011-12-02 12:59:50.0 +0900 +++ libvirt-0.9.8/src/qemu/qemu_command.c 2011-12-12 08:15:39.200968095 +0900 @@ -3061,7 +3061,9 @@ qemuBuildVirtioSerialPortDevStr(virDomai
Re: [libvirt] bug: try to take disk snapshot for LVM2 Volume
Sorry, I confirmed the snapshot file is not wrong. I moved the snapshot file created under /dev as /dev/VG1/abc.xx to other place and fixed the config file re-writed by libvirt to use moved snapshot file abc.xx. So, the domain starts with no problem. Regards MATSUDA Daiki On 11/15/2011 08:20 PM, Dave Allan wrote: After working on this some more, I think that identifying problematic file systems, like devtmpfs, is too tricky to be portable. But I think we can meet halfway - right now, the libvirt code blindly generates a filename if one was not provided, regardless of the file type of the backing file it will be wrapping. But maybe it would be sufficient to make the command error out if no qcow2 filename is provided and the backing file is not a regular file. As in this patch: Ok, now I understand the situation; thanks to everyone for the explanations. I'm somewhat uncomfortable using file type as a proxy for troublesome filesystem since although they are linked in this case, I'm not sure they're linked in all cases. Maybe I'm wrong about that. If there is no portable way to determine whether a particular filesystem is going to be a problem, I would just clearly document the limitations of letting libvirt choose the filename and the importance of not using that functionality on filesystems that cannot hold a useful snapshot. My patch would not be preventing snapshots of block devices, but merely requiring that the user supply the qcow2 filename that will wrap the block device. The problem with just documenting the issue is that someone will fail to read the documentation, perform a default snapshot that creates a problematic qcow2 file, then be upset that their domain fails to boot and that they lost all the changes made since the snapshot. I'm still in favor of this patch if anyone else thinks it is worthwhile. Subject: [PATCH] snapshot: refuse to generate names for non-regular backing files For whatever reason, the kernel allows you to create a regular file named /dev/sdc.12345; although this file will disappear the next time devtmpfs is remounted. If you let libvirt generate the name of the external snapshot for a disk image originally using the block device /dev/sdc, then the domain will be rendered unbootable once the qcow2 file is lost on the next devtmpfs remount. In this case, the user should have used 'virsh snapshot-create --xmlfile' or 'virsh snapshot-create-as --diskspec' to specify the name for the qcow2 file in a sane location, rather than relying on libvirt generating a name that is most likely to be wrong. We can help avoid naive mistakes by enforcing that the user provide the external name for any backing file that is not a regular file. * src/conf/domain_conf.c (virDomainSnapshotAlignDisks): Only generate names if backing file exists as regular file. Reported by MATSUDA Daiki. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] bug: try to take disk snapshot for LVM2 Volume
(2011/11/16 0:35), Dave Allan wrote: On Mon, Nov 14, 2011 at 04:02:21PM -0700, Eric Blake wrote: On 11/13/2011 09:08 PM, MATSUDA, Daiki wrote: NACK. There is nothing inherently wrong with the source file not being a qcow2 file. The whole point of creating a runtime snapshot is that the original file (of _any_ format) becomes the backing file of a new qcow2 file, so that the original file now serves as the snapshot. Forbidding a live snapshot of a raw source file interferes with this intent. I have some tested since you replied. Certainly other image file, e.g. raw type, has no problem after snapshot is taken in qcow2 format. But in the case that direct disk block, e.g. /dev/sdc, is given for the guest OS, the same error occurs. It may not be accepted by qemu-kvm. I'm not following you. As I already said, there's nothing wrong with a direct disk block as the backing file of a qcow2 image. I do not understand which qemu-kvm or libvirt should be fixed. But at least libvirt should be stop to take snapshot for block device with following patch. I still say NACK. Your patch is merely attempting to forbid a useful case, rather than fix a demonstrated problem. Matsuda-san, I must admit that I don't understand the problem that you are attempting to solve either. I have reread the thread from the beginning, but I don't understand what your goal is. Could you explain to us more about your use case? Regards, Dave Allan Mr. Dave. The problem is that the guest does not boot after 'virsh snapshot-create --disk-only' under the specific situation. I tested some cases and found it. 1. The guest use the raw disk volume or LVM2 volume, such as following the config file using raw disk volume created by RHEL 6.1 Virt Manager. domain type='kvm' nameabc/name uuid791ede5a-e617-ca6b-125d-4e9704a2ddc2/uuid memory524288/memory currentMemory524288/currentMemory vcpu1/vcpu os type arch='x86_64' machine='rhel6.1.0'hvm/type boot dev='hd'/ /os features acpi/ apic/ pae/ /features clock offset='utc'/ on_poweroffdestroy/on_poweroff on_rebootrestart/on_reboot on_crashrestart/on_crash devices emulator/usr/libexec/qemu-kvm/emulator disk type='block' device='disk' driver name='qemu' type='raw' cache='none' io='native'/ source dev='/dev/sdc'/ target dev='vda' bus='virtio'/ address type='pci' domain='0x' bus='0x00' slot='0x05' function='0x0'/ /disk disk type='block' device='cdrom' driver name='qemu' type='raw'/ target dev='hdc' bus='ide'/ readonly/ address type='drive' controller='0' bus='1' unit='0'/ /disk controller type='ide' index='0' address type='pci' domain='0x' bus='0x00' slot='0x01' function='0x1'/ /controller interface type='bridge' mac address='52:54:00:0d:53:c6'/ source bridge='br0'/ model type='virtio'/ address type='pci' domain='0x' bus='0x00' slot='0x03' function='0x0'/ /interface serial type='pty' target port='0'/ /serial console type='pty' target type='serial' port='0'/ /console input type='tablet' bus='usb'/ input type='mouse' bus='ps2'/ graphics type='vnc' port='-1' autoport='yes'/ sound model='ich6' address type='pci' domain='0x' bus='0x00' slot='0x04' function='0x0'/ /sound video model type='cirrus' vram='9216' heads='1'/ address type='pci' domain='0x' bus='0x00' slot='0x02' function='0x0'/ /video memballoon model='virtio' address type='pci' domain='0x' bus='0x00' slot='0x06' function='0x0'/ /memballoon /devices /domain 2. Do the 'virsh snapshot-create abc --disk-only' with libvirt-0.9.6 or upper. 3. The guest runs well till it is shutdowned. 4. But the guest does not boot with following error. virtsh # start abc error: Failed to start domain abc error: internal error Process exited while reading console log output: char device redirected to /dev/pts/7 qemu: could not open disk image /dev/sdc.1317357844: Invalid argument. 5. Then the config file has been replaced by libvirtd. Especially difference is disk type='block' device='disk' driver name='qemu' type='qcow2' cache='none'/ source dev='/dev/sdc.1317357844'/ target dev='vda' bus='virtio'/ address type='pci' domain='0x' bus='0x00' slot='0x05' function='0x0'/ /disk And 'snapshot-create ... --disk-only' works well for image format file, e.g. qcow2, raw and etc. So, I think that the restriction is needed for the taking snapshot disk-only for the disk volume. Regards MATSUDA Daiki If I recall correctly, you started this thread when you used 'virsh snapshot-create --disk-only' without arguments, and thus fell victim to virsh picking the snapshot name for you, but trying to pick that name under /dev instead of a more typical location for a non-device file. But that's a usage error in you not taking time
Re: [libvirt] bug: try to take disk snapshot for LVM2 Volume
On 11/06/2011 09:14 PM, MATSUDA, Daiki wrote: I made the patch for the problem to take the snapshot but qcow2. It use the 'qemu-img' command, I know that it is not essential solution. But I think it is better than to link qemu's libraries. Regards @@ -9002,6 +9021,13 @@ qemuDomainSnapshotCreateSingleDiskActive return -1; } +ret = qemuDomainSnapshotCheckSrcQcow2(src-disk); +if (ret) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(src image is not qcow2 format)); +return ret; +} NACK. There is nothing inherently wrong with the source file not being a qcow2 file. The whole point of creating a runtime snapshot is that the original file (of _any_ format) becomes the backing file of a new qcow2 file, so that the original file now serves as the snapshot. Forbidding a live snapshot of a raw source file interferes with this intent. I have some tested since you replied. Certainly other image file, e.g. raw type, has no problem after snapshot is taken in qcow2 format. But in the case that direct disk block, e.g. /dev/sdc, is given for the guest OS, the same error occurs. It may not be accepted by qemu-kvm. I do not understand which qemu-kvm or libvirt should be fixed. But at least libvirt should be stop to take snapshot for block device with following patch. Regards MATSUDA Daiki --- libvirt-0.9.7.orig/src/qemu/qemu_driver.c 2011-11-03 23:48:23.0 +0900 +++ libvirt-0.9.7/src/qemu/qemu_driver.c2011-11-14 12:56:51.870453885 +0900 @@ -9025,6 +9025,7 @@ qemuDomainSnapshotCreateSingleDiskActive char *origsrc = NULL; char *origdriver = NULL; bool need_unlink = false; +struct stat sb; if (snap-snapshot != VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL) { qemuReportError(VIR_ERR_INTERNAL_ERROR, %s, @@ -9032,6 +9033,17 @@ qemuDomainSnapshotCreateSingleDiskActive return -1; } +if (stat(disk-src, sb) 0) { +virReportSystemError(errno, + _(unable to stat for disk %s), + disk-src); +} +if (S_ISBLK(sb.st_mode)) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(src image is Block Device)); +return -1; +} + if (virAsprintf(device, drive-%s, disk-info.alias) 0 || !(source = strdup(snap-file)) || (STRNEQ_NULLABLE(disk-driverType, qcow2) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] bug: try to take disk snapshot for LVM2 Volume
Hi, Eric. On 09/29/2011 11:26 PM, MATSUDA, Daiki wrote: I tried the new snapshot function implemented by Eric Blake. It works very well for QCOW2 disk image system. But I often use LVM2 volume for QEMU virtual machines and tried to take disk snapshot by virsh command ( snapshot-create DOMNAME --disk-only). So, finally qemu monitor command 'snapshot_blkdev' accepts the LVM2 volume and create QCOW2 snapshot image. In addition, domain's configuration file is replaced to use snapshot disk image instead of LVM2 volume. It sounds like virsh did what it was told, but that you told it so little information that it had to fill in the gaps and choose its own destination file name (hence the .1317357844 suffix after the action). Your situation sounds like a case where you may want a bit more control over the destination file name. I made the patch for the problem to take the snapshot but qcow2. It use the 'qemu-img' command, I know that it is not essential solution. But I think it is better than to link qemu's libraries. Regards MATSUDA Daiki diff -uNrp libvirt-0.9.7.orig/src/qemu/qemu_driver.c libvirt-0.9.7/src/qemu/qemu_driver.c --- libvirt-0.9.7.orig/src/qemu/qemu_driver.c 2011-10-31 12:46:04.0 +0900 +++ libvirt-0.9.7/src/qemu/qemu_driver.c2011-11-07 13:03:07.162639142 +0900 @@ -8976,6 +8976,25 @@ cleanup: return ret; } +static int ATTRIBUTE_NONNULL(1) +qemuDomainSnapshotCheckSrcQcow2(const char *src) +{ +const char *qemuimgarg[] = {NULL, check, -f, qcow2, NULL, NULL}; +int ret = -1; + +qemuimgarg[0] = virFindFileInPath(qemu-img); +if (!qemuimgarg[0]) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(unable to find qemu-img)); +return ret; +} +qemuimgarg[4] = src; + +ret = virRun(qemuimgarg, NULL); +VIR_FREE(qemuimgarg[0]); +return ret; +} + /* The domain is expected to hold monitor lock. */ static int qemuDomainSnapshotCreateSingleDiskActive(struct qemud_driver *driver, @@ -9002,6 +9021,13 @@ qemuDomainSnapshotCreateSingleDiskActive return -1; } +ret = qemuDomainSnapshotCheckSrcQcow2(src-disk); +if (ret) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(src image is not qcow2 format)); +return ret; +} + if (virAsprintf(device, drive-%s, disk-info.alias) 0 || !(source = strdup(snap-file)) || (STRNEQ_NULLABLE(disk-driverType, qcow2) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/4] Add new virDomainShutdownFlags API
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 83f4f3c..eaf8bbd 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -4312,6 +4312,7 @@ static virDriver remote_driver = { .domainSuspend = remoteDomainSuspend, /* 0.3.0 */ .domainResume = remoteDomainResume, /* 0.3.0 */ .domainShutdown = remoteDomainShutdown, /* 0.3.0 */ +.domainShutdownFlags = remoteDomainShutdownFlags, /* 0.9.7 */ .domainReboot = remoteDomainReboot, /* 0.3.0 */ .domainReset = remoteDomainReset, /* 0.9.7 */ .domainDestroy = remoteDomainDestroy, /* 0.3.0 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index c8a92fd..34e4b2a 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2234,6 +2234,12 @@ struct remote_domain_get_control_info_ret { /* insert@1 */ unsigned hyper stateTime; }; +struct remote_domain_shutdown_flags_args { +remote_nonnull_domain dom; +unsigned int flags; +}; + + /*- Protocol. -*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -2525,7 +2531,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED = 242, /* autogen autogen */ REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /* autogen autogen */ -REMOTE_PROC_DOMAIN_RESET = 245 /* autogen autogen */ +REMOTE_PROC_DOMAIN_RESET = 245, /* autogen autogen */ +REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 246 /* autogen autogen */ /* * Notice how the entries are grouped in sets of 10 ? I think it does not works well if target is localhost or not, because remoteDomainShutdownFlags() function is not implemented. So, do you have a plan ? MATSUDA Daiki -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/4] Add support for QEMU guest agent control
(2011/10/06 2:31), Daniel P. Berrange wrote: The QEMU guest agent /usr/bin/qemu-ga has some handy functions for controlling the guest, not least, shutdown/reboot and filesystem freeze/thaw. In Fedora 15/16 the semantics of the ACPI power button have been changed to suspend-to-RAM which breaks our current shutdown implementation. By adding support for the agent we gain a more predictable way to shutdown / reboot guests. NB: the code currently has the same flaw as the monitor, in so much as we wait forever for a guest agent reply. We need to add a timeout ability to the agent code -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list The QEMU guest agent has other function FS Freeze. But your patches does not support it. Do you have a plan ? In addition, the QEMU guest agent requires specified socket. Virt IO Console, too. But unfortunately libvirt does not support to xml tags to give socket name options to QEMU for the QEMU guest agent and Virt IO Console. MATSUDA Daiki -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] bug: try to take disk snapshot for LVM2 Volume
On 09/29/2011 11:26 PM, MATSUDA, Daiki wrote: I tried the new snapshot function implemented by Eric Blake. It works very well for QCOW2 disk image system. But I often use LVM2 volume for QEMU virtual machines and tried to take disk snapshot by virsh command ( snapshot-create DOMNAME --disk-only). So, finally qemu monitor command 'snapshot_blkdev' accepts the LVM2 volume and create QCOW2 snapshot image. In addition, domain's configuration file is replaced to use snapshot disk image instead of LVM2 volume. It sounds like virsh did what it was told, but that you told it so little information that it had to fill in the gaps and choose its own destination file name (hence the .1317357844 suffix after the action). Your situation sounds like a case where you may want a bit more control over the destination file name. virsh outputs virsh # snapshot-create LVM2_dom --disk-only Domain snapshot 1317357844 created And I confirmed that the qcow2 image file is created under /dev/VG1 # file /dev/VG1/LVM2_dom.1317357844 /dev/VG1/LVM2_dom.1317686816: Qemu Image, Format: Qcow , Version: 2 configuration file from disk type='block' device='disk driver name='qemu' type='raw' cache='none'/ source dev='dev/VG1/LVM2_dom'/ to disk type='block' device='disk driver name='qemu' type='qcow2' cache='none'/ source dev='dev/VG1/LVM2_dom.1317357844'/ Are you pasting literal chunks, or retyping this? You're missing the / in front of dev/VG1, so I can't help but wonder what else might have been mistyped. I am sorry. They are my mistyping and correct is '/dev/VG1/LVM2_dom' and '/dev/VG1/LVM2_dom.1317357844'. After then, the domain runs well till it is shutdowned. I'm surprised that it got that far - generally, libvirt can't create random regular files under the /dev/VG1/ device-mapper hierarchy, and if a file can't be created, then what was open() doing, and what did qemu actually do? It may be worth looking at lsof says that qemu has open, if you still have it running. Or it may be that you've found a bug in libvirt and/or qemu for not accurately reporting failure to create the snapshot image. But in reality the file is created by qemu-kvm with snapshot_blkdev in qemu-monitor command. I use libvirt-0.9.6 and qemu-kvm-0.12.12.1.2-2.160 and August's snapshot. I think we need to step back a bit and look at the bigger picture. Do you want your new qcow2 file to be its own LVM volume (in which case, I'd suggest that you pre-create the LVM volume, and pass in the file name within /dev/VG1/ of the existing block device to use), or are you okay with it being a regular file (in which case, I'd suggest that you do not pre-create the file, but that you still pass in the desired filename to some absolute path that lives outside of /dev/)? No, I do not want qcow2 file on LVM volume. I found the bug at simply tesing. I will never create the snapshot with 'snapshot-create ... --disk-only' for LVM2 volume, but users will try... So, I think that it is better not to refuse in libvirt. Either way, it sounds like you do _not_ want libvirt to be generating its own filename, since libvirt only knows how to generate a name in the same directory as the snapshot is taking place, but your lvm is in a special directory. To do this, you either need to create an XML file yourself, and call 'virsh snapshot-create dom --disk-only file', or you need to have virsh create the xml for you with 'virsh snapshot-create-as dom --disk-only vda,file=/path/to/file'. You can see the xml that snapshot-create-as would generate (in case you need to further fine-tune it for your own use in snapshot-create) via the --print-xml option. I started the domain, but it does not with following error virtsh # start LVM2_dom error: Failed to start domain LVM2_dom error: 内部エラー Process exited while reading console log output: char device redirected to /dev/pts/7 qemu: could not open disk image /dev/VG1/LVM2_dom.1317357844: Invalid argument. That makes sense, if that file doesn't exist (but why qemu didn't reject the snapshot in the first place still remains to be investigated). I think that if the volume but qcow2 is given libvirt should be refuse, No, qemu does just fine with a non-qcow2 backing file. The real problem here is that the new qcow2 file was not created, not the type of the original file. At least its phenomenon is reproduced easily. So I hope you test. e.g. in qemuDomainSnapshotCreateDiskActive() with voulme driver type. But currently the structures concerning with snapshot or disk has no member to hold such a volume driver information. In addition, as we want to add the LVM2 and other volume snapshot function, we hope you add its information and fix. Yes, I have much longer-term plans for refactoring device snapshots to move the work into more virStorageVolPtr operations, and teach virDomainSnapshotCreateXML to reuse virStorageVol actions rather
Re: [libvirt] bug: try to take disk snapshot for LVM2 Volume
(2011/09/30 14:26), MATSUDA, Daiki wrote: I tried the new snapshot function implemented by Eric Blake. It works very well for QCOW2 disk image system. But I often use LVM2 volume for QEMU virtual machines and tried to take disk snapshot by virsh command ( snapshot-create DOMNAME --disk-only). So, finally qemu monitor command 'snapshot_blkdev' accepts the LVM2 volume and create QCOW2 snapshot image. In addition, domain's configuration file is replaced to use snapshot disk image instead of LVM2 volume. configuration file from disk type='block' device='disk driver name='qemu' type='raw' cache='none'/ source dev='dev/VG1/LVM2_dom'/ to disk type='block' device='disk driver name='qemu' type='qcow2' cache='none'/ source dev='dev/VG1/LVM2_dom.1317357844'/ After then, the domain runs well till it is shutdowned. I started the domain, but it does not with following error virtsh # start LVM2_dom error: Failed to start domain LVM2_dom error: 内部エラー Process exited while reading console log output: char Sorry, upper is error: internal error Process exited while reading console log output: char device redirected to /dev/pts/7 qemu: could not open disk image /dev/VG1/LVM2_dom.1317357844: Invalid argument. I think that if the volume but qcow2 is given libvirt should be refuse, e.g. in qemuDomainSnapshotCreateDiskActive() with voulme driver type. But currently the structures concerning with snapshot or disk has no member to hold such a volume driver information. In addition, as we want to add the LVM2 and other volume snapshot function, we hope you add its information and fix. Regards MATSUDA Daiki -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] bug: try to take disk snapshot for LVM2 Volume
I tried the new snapshot function implemented by Eric Blake. It works very well for QCOW2 disk image system. But I often use LVM2 volume for QEMU virtual machines and tried to take disk snapshot by virsh command ( snapshot-create DOMNAME --disk-only). So, finally qemu monitor command 'snapshot_blkdev' accepts the LVM2 volume and create QCOW2 snapshot image. In addition, domain's configuration file is replaced to use snapshot disk image instead of LVM2 volume. configuration file from disk type='block' device='disk driver name='qemu' type='raw' cache='none'/ source dev='dev/VG1/LVM2_dom'/ to disk type='block' device='disk driver name='qemu' type='qcow2' cache='none'/ source dev='dev/VG1/LVM2_dom.1317357844'/ After then, the domain runs well till it is shutdowned. I started the domain, but it does not with following error virtsh # start LVM2_dom error: Failed to start domain LVM2_dom error: 内部エラー Process exited while reading console log output: char device redirected to /dev/pts/7 qemu: could not open disk image /dev/VG1/LVM2_dom.1317357844: Invalid argument. I think that if the volume but qcow2 is given libvirt should be refuse, e.g. in qemuDomainSnapshotCreateDiskActive() with voulme driver type. But currently the structures concerning with snapshot or disk has no member to hold such a volume driver information. In addition, as we want to add the LVM2 and other volume snapshot function, we hope you add its information and fix. Regards MATSUDA Daiki -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list