提交 6f9c75a6 编写于 作者: M Michal Privoznik

qemu: Implement virDomain{Get,Set}Time

One caveat though, qemu-ga is expecting time and returning time
in nanoseconds. With all the buffering and propagation delay, the
time is already wrong once it gets to the qemu-ga, but there's
nothing we can do about it.
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 222fdbfd
......@@ -1685,3 +1685,96 @@ qemuAgentUpdateCPUInfo(unsigned int nvcpus,
return 0;
}
int
qemuAgentGetTime(qemuAgentPtr mon,
long long *seconds,
unsigned int *nseconds)
{
int ret = -1;
unsigned long long json_time;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
cmd = qemuAgentMakeCommand("guest-get-time",
NULL);
if (!cmd)
return ret;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
goto cleanup;
if (virJSONValueObjectGetNumberUlong(reply, "return", &json_time) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("malformed return value"));
goto cleanup;
}
/* guest agent returns time in nanoseconds,
* we need it in seconds here */
*seconds = json_time / 1000000000LL;
*nseconds = json_time % 1000000000LL;
ret = 0;
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
/**
* qemuAgentSetTime:
* @setTime: time to set
* @sync: let guest agent to read domain's RTC (@setTime is ignored)
*/
int
qemuAgentSetTime(qemuAgentPtr mon,
long long seconds,
unsigned int nseconds,
bool sync)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (sync) {
cmd = qemuAgentMakeCommand("guest-set-time", NULL);
} else {
/* guest agent expect time with nanosecond granularity.
* Impressing. */
long long json_time;
/* Check if we overflow. For some reason qemu doesn't handle unsigned
* long long on the monitor well as it silently truncates numbers to
* signed long long. Therefore we must check overflow against LLONG_MAX
* not ULLONG_MAX. */
if (seconds > LLONG_MAX / 1000000000LL) {
virReportError(VIR_ERR_INVALID_ARG,
_("Time '%lld' is too big for guest agent"),
seconds);
return ret;
}
json_time = seconds * 1000000000LL;
json_time += nseconds;
cmd = qemuAgentMakeCommand("guest-set-time",
"I:time", json_time,
NULL);
}
if (!cmd)
return ret;
if (qemuAgentCommand(mon, cmd, &reply, true,
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
goto cleanup;
ret = 0;
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
......@@ -98,4 +98,12 @@ int qemuAgentSetVCPUs(qemuAgentPtr mon, qemuAgentCPUInfoPtr cpus, size_t ncpus);
int qemuAgentUpdateCPUInfo(unsigned int nvcpus,
qemuAgentCPUInfoPtr cpuinfo,
int ncpuinfo);
int qemuAgentGetTime(qemuAgentPtr mon,
long long *seconds,
unsigned int *nseconds);
int qemuAgentSetTime(qemuAgentPtr mon,
long long seconds,
unsigned int nseconds,
bool sync);
#endif /* __QEMU_AGENT_H__ */
......@@ -16536,6 +16536,113 @@ qemuConnectGetCPUModelNames(virConnectPtr conn,
return cpuGetModels(arch, models);
}
static int
qemuDomainGetTime(virDomainPtr dom,
long long *seconds,
unsigned int *nseconds,
unsigned int flags)
{
virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm = NULL;
qemuDomainObjPrivatePtr priv;
int ret = -1;
int rv;
virCheckFlags(0, ret);
if (!(vm = qemuDomObjFromDomain(dom)))
return ret;
if (virDomainGetTimeEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
priv = vm->privateData;
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
goto cleanup;
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
}
if (!qemuDomainAgentAvailable(priv, true))
goto endjob;
qemuDomainObjEnterAgent(vm);
rv = qemuAgentGetTime(priv->agent, seconds, nseconds);
qemuDomainObjExitAgent(vm);
if (rv < 0)
goto endjob;
ret = 0;
endjob:
if (!qemuDomainObjEndJob(driver, vm))
vm = NULL;
cleanup:
if (vm)
virObjectUnlock(vm);
return ret;
}
static int
qemuDomainSetTime(virDomainPtr dom,
long long seconds,
unsigned int nseconds,
unsigned int flags)
{
virQEMUDriverPtr driver = dom->conn->privateData;
qemuDomainObjPrivatePtr priv;
virDomainObjPtr vm;
bool sync = flags & VIR_DOMAIN_TIME_SYNC;
int ret = -1;
int rv;
virCheckFlags(VIR_DOMAIN_TIME_SYNC, ret);
if (!(vm = qemuDomObjFromDomain(dom)))
return ret;
if (virDomainSetTimeEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
priv = vm->privateData;
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;
}
if (!qemuDomainAgentAvailable(priv, true))
goto endjob;
qemuDomainObjEnterAgent(vm);
rv = qemuAgentSetTime(priv->agent, seconds, nseconds, sync);
qemuDomainObjExitAgent(vm);
if (rv < 0)
goto endjob;
ret = 0;
endjob:
if (!qemuDomainObjEndJob(driver, vm))
vm = NULL;
cleanup:
if (vm)
virObjectUnlock(vm);
return ret;
}
static int
qemuDomainFSFreeze(virDomainPtr dom,
......@@ -16819,6 +16926,8 @@ static virDriver qemuDriver = {
.connectGetCPUModelNames = qemuConnectGetCPUModelNames, /* 1.1.3 */
.domainFSFreeze = qemuDomainFSFreeze, /* 1.2.5 */
.domainFSThaw = qemuDomainFSThaw, /* 1.2.5 */
.domainGetTime = qemuDomainGetTime, /* 1.2.5 */
.domainSetTime = qemuDomainSetTime, /* 1.2.5 */
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册