提交 a931486a 编写于 作者: J Jonathon Jongsma 提交者: Michal Privoznik

qemu: guestinfo: handle unsupported agent commands

When we're collecting guest information, older agents may not support
all agent commands. In the case where the user requested all info
types (i.e. types == 0), ignore unsupported command errors and gather as
much information as possible. If the agent command failed for some other
reason, or if the user explciitly requested a specific info type (i.e.
types != 0), abort on the first error.
Signed-off-by: NJonathon Jongsma <jjongsma@redhat.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Reviewed-by: NMichal Privoznik <mprivozn@redhat.com>
上级 56cac62b
......@@ -995,6 +995,26 @@ qemuAgentStringifyErrorClass(const char *klass)
return "unknown QEMU command error";
}
/* Checks whether the agent reply msg is an error caused by an unsupported
* command.
*
* Returns true when reply is CommandNotFound or CommandDisabled
* false otherwise
*/
static bool
qemuAgentErrorCommandUnsupported(virJSONValuePtr reply)
{
const char *klass;
virJSONValuePtr error = virJSONValueObjectGet(reply, "error");
if (!error)
return false;
klass = virJSONValueObjectGetString(error, "class");
return STREQ_NULLABLE(klass, "CommandNotFound") ||
STREQ_NULLABLE(klass, "CommandDisabled");
}
/* Ignoring OOM in this method, since we're already reporting
* a more important error
*
......@@ -1708,8 +1728,11 @@ qemuAgentGetHostname(qemuAgentPtr mon,
return ret;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
if (qemuAgentErrorCommandUnsupported(reply))
ret = -2;
goto cleanup;
}
if (!(data = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
......@@ -2005,6 +2028,10 @@ qemuAgentGetFSInfoInternalDisk(virJSONValuePtr jsondisks,
return 0;
}
/* Returns: 0 on success
* -2 when agent command is not supported by the agent
* -1 otherwise
*/
static int
qemuAgentGetFSInfoInternal(qemuAgentPtr mon,
qemuAgentFSInfoPtr **info,
......@@ -2023,8 +2050,11 @@ qemuAgentGetFSInfoInternal(qemuAgentPtr mon,
return ret;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
if (qemuAgentErrorCommandUnsupported(reply))
ret = -2;
goto cleanup;
}
if (!(data = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
......@@ -2141,6 +2171,9 @@ qemuAgentGetFSInfoInternal(qemuAgentPtr mon,
return ret;
}
/* Returns: 0 on success
* -1 otherwise
*/
int
qemuAgentGetFSInfo(qemuAgentPtr mon,
virDomainFSInfoPtr **info,
......@@ -2178,6 +2211,10 @@ qemuAgentGetFSInfo(qemuAgentPtr mon,
return ret;
}
/* Returns: 0 on success
* -2 when agent command is not supported by the agent
* -1 otherwise
*/
int
qemuAgentGetFSInfoParams(qemuAgentPtr mon,
virTypedParameterPtr *params,
......@@ -2190,7 +2227,7 @@ qemuAgentGetFSInfoParams(qemuAgentPtr mon,
int nfs;
if ((nfs = qemuAgentGetFSInfoInternal(mon, &fsinfo, vmdef)) < 0)
return -1;
return nfs;
if (virTypedParamsAddUInt(params, nparams, maxparams,
"fs.count", nfs) < 0)
......@@ -2499,6 +2536,10 @@ qemuAgentSetUserPassword(qemuAgentPtr mon,
return ret;
}
/* Returns: 0 on success
* -2 when agent command is not supported by the agent
* -1 otherwise
*/
int
qemuAgentGetUsers(qemuAgentPtr mon,
virTypedParameterPtr *params,
......@@ -2515,8 +2556,11 @@ qemuAgentGetUsers(qemuAgentPtr mon,
return -1;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
if (qemuAgentErrorCommandUnsupported(reply))
return -2;
return -1;
}
if (!(data = virJSONValueObjectGetArray(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
......@@ -2584,6 +2628,10 @@ qemuAgentGetUsers(qemuAgentPtr mon,
return ndata;
}
/* Returns: 0 on success
* -2 when agent command is not supported by the agent
* -1 otherwise
*/
int
qemuAgentGetOSInfo(qemuAgentPtr mon,
virTypedParameterPtr *params,
......@@ -2598,8 +2646,11 @@ qemuAgentGetOSInfo(qemuAgentPtr mon,
return -1;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
if (qemuAgentErrorCommandUnsupported(reply))
return -2;
return -1;
}
if (!(data = virJSONValueObjectGetObject(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
......@@ -2631,6 +2682,10 @@ qemuAgentGetOSInfo(qemuAgentPtr mon,
return 0;
}
/* Returns: 0 on success
* -2 when agent command is not supported by the agent
* -1 otherwise
*/
int
qemuAgentGetTimezone(qemuAgentPtr mon,
virTypedParameterPtr *params,
......@@ -2647,8 +2702,11 @@ qemuAgentGetTimezone(qemuAgentPtr mon,
return -1;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0) {
if (qemuAgentErrorCommandUnsupported(reply))
return -2;
return -1;
}
if (!(data = virJSONValueObjectGetObject(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
......
......@@ -23220,6 +23220,7 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
int maxparams = 0;
VIR_AUTOFREE(char *) hostname = NULL;
unsigned int supportedTypes = types;
int rc;
virCheckFlags(0, -1);
qemuDomainGetGuestInfoCheckSupport(&supportedTypes);
......@@ -23240,30 +23241,30 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
agent = qemuDomainObjEnterAgent(vm);
/* Although the libvirt qemu driver supports all of these guest info types,
* some guest agents might be too old to support these commands. If these
* info categories were explicitly requested (i.e. 'types' is non-zero),
* abort and report an error on any failures, otherwise continue and return
* as much info as is supported by the guest agent. */
/* The agent info commands will return -2 for any commands that are not
* supported by the agent, or -1 for all other errors. In the case where no
* categories were explicitly requested (i.e. 'types' is 0), ignore
* 'unsupported' errors and gather as much information as we can. In all
* other cases, abort on error. */
if (supportedTypes & VIR_DOMAIN_GUEST_INFO_USERS) {
if (qemuAgentGetUsers(agent, params, nparams, &maxparams) < 0 &&
types != 0)
rc = qemuAgentGetUsers(agent, params, nparams, &maxparams);
if (rc < 0 && !(rc == -2 && types == 0))
goto exitagent;
}
if (supportedTypes & VIR_DOMAIN_GUEST_INFO_OS) {
if (qemuAgentGetOSInfo(agent, params, nparams, &maxparams) < 0
&& types != 0)
rc = qemuAgentGetOSInfo(agent, params, nparams, &maxparams);
if (rc < 0 && !(rc == -2 && types == 0))
goto exitagent;
}
if (supportedTypes & VIR_DOMAIN_GUEST_INFO_TIMEZONE) {
if (qemuAgentGetTimezone(agent, params, nparams, &maxparams) < 0
&& types != 0)
rc = qemuAgentGetTimezone(agent, params, nparams, &maxparams);
if (rc < 0 && !(rc == -2 && types == 0))
goto exitagent;
}
if (supportedTypes & VIR_DOMAIN_GUEST_INFO_HOSTNAME) {
if (qemuAgentGetHostname(agent, &hostname) < 0) {
if (types != 0)
goto exitagent;
rc = qemuAgentGetHostname(agent, &hostname);
if (rc < 0 && !(rc == -2 && types == 0)) {
goto exitagent;
} else {
if (virTypedParamsAddString(params, nparams, &maxparams, "hostname",
hostname) < 0)
......@@ -23271,8 +23272,8 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
}
}
if (supportedTypes & VIR_DOMAIN_GUEST_INFO_FILESYSTEM) {
if (qemuAgentGetFSInfoParams(agent, params, nparams, &maxparams, vm->def) < 0 &&
types != 0)
rc = qemuAgentGetFSInfoParams(agent, params, nparams, &maxparams, vm->def);
if (rc < 0 && !(rc == -2 && types == 0))
goto exitagent;
}
......
......@@ -462,7 +462,7 @@ testQemuAgentGetFSInfoParams(const void *data)
goto cleanup;
if (qemuAgentGetFSInfoParams(qemuMonitorTestGetAgent(test), &params,
&nparams, &maxparams, def) != -1) {
&nparams, &maxparams, def) != -2) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"agent get-fsinfo command should have failed");
goto cleanup;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册