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;
+}
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,
.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 */
};