/** * qemuAgentGuestSync: * @mon: Monitor * * Send guest-sync with unique ID * and wait for reply. If we get one, check if * received ID is equal to given. * * Returns: 0 on success, * -1 otherwise */ static int qemuAgentGuestSync(qemuAgentPtr mon) { int ret = -1; int send_ret; unsigned long long id, id_ret; qemuAgentMessage sync_msg; memset(&sync_msg, 0, sizeof(sync_msg)); if (virTimeMillisNow(&id) < 0) return -1; if (virAsprintf(&sync_msg.txBuffer, "{\"execute\":\"guest-sync\", " "\"arguments\":{\"id\":%llu}}", id) < 0) { virReportOOMError(); return -1; } sync_msg.txLength = strlen(sync_msg.txBuffer); VIR_DEBUG("Sending guest-sync command with ID: %llu", id); send_ret = qemuAgentSend(mon, &sync_msg, true); VIR_DEBUG("qemuAgentSend returned: %d", send_ret); if (send_ret < 0) { /* error reported */ goto cleanup; } if (!sync_msg.rxObject) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing monitor reply object")); goto cleanup; } if (virJSONValueObjectGetNumberUlong(sync_msg.rxObject, "return", &id_ret) < 0) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Malformed return value")); goto cleanup; } VIR_DEBUG("Guest returned ID: %llu", id_ret); if (id_ret != id) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("Guest agent returned ID: %llu instead of %llu"), id_ret, id); goto cleanup; } ret = 0; cleanup: virJSONValueFree(sync_msg.rxObject); VIR_FREE(sync_msg.txBuffer); return ret; }
static int qemuAgentIOProcessLine(qemuAgentPtr mon, const char *line, qemuAgentMessagePtr msg) { virJSONValuePtr obj = NULL; int ret = -1; unsigned long long id; VIR_DEBUG("Line [%s]", line); if (!(obj = virJSONValueFromString(line))) goto cleanup; if (obj->type != VIR_JSON_TYPE_OBJECT) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Parsed JSON reply '%s' isn't an object"), line); goto cleanup; } if (virJSONValueObjectHasKey(obj, "QMP") == 1) { ret = 0; } else if (virJSONValueObjectHasKey(obj, "event") == 1) { ret = qemuAgentIOProcessEvent(mon, obj); } else if (virJSONValueObjectHasKey(obj, "error") == 1 || virJSONValueObjectHasKey(obj, "return") == 1) { if (msg) { msg->rxObject = obj; msg->finished = 1; obj = NULL; ret = 0; } else { /* If we've received something like: * {"return": 1234} * it is likely that somebody started GA * which is now processing our previous * guest-sync commands. Check if this is * the case and don't report an error but * return silently. */ if (virJSONValueObjectGetNumberUlong(obj, "return", &id) == 0) { VIR_DEBUG("Ignoring delayed reply to guest-sync: %llu", id); ret = 0; goto cleanup; } virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected JSON reply '%s'"), line); } } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown JSON reply '%s'"), line); } cleanup: virJSONValueFree(obj); return ret; }
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; }
virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr object, virNetServerClientPrivNewPostExecRestart privNew, virNetServerClientPrivPreExecRestart privPreExecRestart, virFreeCallback privFree, void *privOpaque, void *opaque) { virJSONValuePtr child; virNetServerClientPtr client = NULL; virNetSocketPtr sock; int auth; bool readonly; unsigned int nrequests_max; unsigned long long id; long long timestamp; if (virJSONValueObjectGetNumberInt(object, "auth", &auth) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing auth field in JSON state document")); return NULL; } if (virJSONValueObjectGetBoolean(object, "readonly", &readonly) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing readonly field in JSON state document")); return NULL; } if (virJSONValueObjectGetNumberUint(object, "nrequests_max", &nrequests_max) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing nrequests_client_max field in JSON state document")); return NULL; } if (!(child = virJSONValueObjectGet(object, "sock"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing sock field in JSON state document")); return NULL; } if (!virJSONValueObjectHasKey(object, "id")) { /* no ID found in, a new one must be generated */ id = virNetServerNextClientID((virNetServerPtr) opaque); } else { if (virJSONValueObjectGetNumberUlong(object, "id", &id) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Malformed id field in JSON state document")); return NULL; } } if (!virJSONValueObjectHasKey(object, "conn_time")) { timestamp = 0; } else { if (virJSONValueObjectGetNumberLong(object, "conn_time", ×tamp) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Malformed conn_time field in JSON " "state document")); return NULL; } } if (!(sock = virNetSocketNewPostExecRestart(child))) { virObjectUnref(sock); return NULL; } if (!(client = virNetServerClientNewInternal(id, sock, auth, #ifdef WITH_GNUTLS NULL, #endif readonly, nrequests_max, timestamp))) { virObjectUnref(sock); return NULL; } virObjectUnref(sock); if (privNew) { if (!(child = virJSONValueObjectGet(object, "privateData"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing privateData field in JSON state document")); goto error; } if (!(client->privateData = privNew(client, child, privOpaque))) goto error; client->privateDataFreeFunc = privFree; client->privateDataPreExecRestart = privPreExecRestart; } return client; error: virObjectUnref(client); return NULL; }
virNetServerClientPtr virNetServerClientNewPostExecRestart(virNetServerPtr srv, virJSONValuePtr object, virNetServerClientPrivNewPostExecRestart privNew, virNetServerClientPrivPreExecRestart privPreExecRestart, virFreeCallback privFree, void *privOpaque) { virJSONValuePtr child; virNetServerClientPtr client = NULL; virNetSocketPtr sock; int auth; bool readonly, auth_pending; unsigned int nrequests_max; unsigned long long id; long long timestamp; if (virJSONValueObjectGetNumberInt(object, "auth", &auth) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing auth field in JSON state document")); return NULL; } if (!virJSONValueObjectHasKey(object, "auth_pending")) { auth_pending = !virNetServerClientAuthMethodImpliesAuthenticated(auth); } else { if (virJSONValueObjectGetBoolean(object, "auth_pending", &auth_pending) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Malformed auth_pending field in JSON state document")); return NULL; } /* If the used authentication method implies that the new * client is automatically authenticated, the authentication * cannot be pending */ if (auth_pending && virNetServerClientAuthMethodImpliesAuthenticated(auth)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid auth_pending and auth combination in JSON state document")); return NULL; } } if (virJSONValueObjectGetBoolean(object, "readonly", &readonly) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing readonly field in JSON state document")); return NULL; } if (virJSONValueObjectGetNumberUint(object, "nrequests_max", &nrequests_max) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing nrequests_client_max field in JSON state document")); return NULL; } if (!(child = virJSONValueObjectGet(object, "sock"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing sock field in JSON state document")); return NULL; } if (!virJSONValueObjectHasKey(object, "id")) { /* no ID found in, a new one must be generated */ id = virNetServerNextClientID(srv); } else { if (virJSONValueObjectGetNumberUlong(object, "id", &id) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Malformed id field in JSON state document")); return NULL; } } if (!virJSONValueObjectHasKey(object, "conn_time")) { timestamp = 0; } else { if (virJSONValueObjectGetNumberLong(object, "conn_time", ×tamp) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Malformed conn_time field in JSON " "state document")); return NULL; } } if (!(sock = virNetSocketNewPostExecRestart(child))) { virObjectUnref(sock); return NULL; } if (!(client = virNetServerClientNewInternal(id, sock, auth, auth_pending, NULL, readonly, nrequests_max, timestamp))) { virObjectUnref(sock); return NULL; } virObjectUnref(sock); if (!(child = virJSONValueObjectGet(object, "privateData"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing privateData field in JSON state document")); goto error; } if (!(client->privateData = privNew(client, child, privOpaque))) goto error; client->privateDataFreeFunc = privFree; client->privateDataPreExecRestart = privPreExecRestart; return client; error: virObjectUnref(client); return NULL; }