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; }
int qemuAgentArbitraryCommand(qemuAgentPtr mon, const char *cmd_str, char **result, int timeout) { int ret = -1; virJSONValuePtr cmd = NULL; virJSONValuePtr reply = NULL; *result = NULL; if (timeout < VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN) { virReportError(VIR_ERR_INVALID_ARG, _("guest agent timeout '%d' is " "less than the minimum '%d'"), timeout, VIR_DOMAIN_QEMU_AGENT_COMMAND_MIN); goto cleanup; } if (!(cmd = virJSONValueFromString(cmd_str))) goto cleanup; if ((ret = qemuAgentCommand(mon, cmd, &reply, true, timeout)) < 0) goto cleanup; if (!(*result = virJSONValueToString(reply, false))) ret = -1; cleanup: virJSONValueFree(cmd); virJSONValueFree(reply); return ret; }
static int testQemuDiskXMLToPropsValidateSchema(const void *opaque) { struct testQemuDiskXMLToJSONData *data = (void *) opaque; virBuffer debug = VIR_BUFFER_INITIALIZER; char *propsstr = NULL; char *debugmsg = NULL; int ret = 0; size_t i; if (data->fail) return EXIT_AM_SKIP; for (i = 0; i < data->nprops; i++) { if (testQEMUSchemaValidate(data->props[i], data->schemaroot, data->schema, &debug) < 0) { debugmsg = virBufferContentAndReset(&debug); propsstr = virJSONValueToString(data->props[i], true); VIR_TEST_VERBOSE("json does not conform to QAPI schema"); VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s", propsstr, NULLSTR(debugmsg)); VIR_FREE(debugmsg); VIR_FREE(propsstr); ret = -1; } virBufferFreeAndReset(&debug); } return ret; }
static int qemuAgentCommand(qemuAgentPtr mon, virJSONValuePtr cmd, virJSONValuePtr *reply, int seconds) { int ret = -1; qemuAgentMessage msg; char *cmdstr = NULL; int await_event = mon->await_event; *reply = NULL; if (qemuAgentGuestSync(mon) < 0) { /* helper reported the error */ return -1; } memset(&msg, 0, sizeof(msg)); if (!(cmdstr = virJSONValueToString(cmd, false))) { virReportOOMError(); goto cleanup; } if (virAsprintf(&msg.txBuffer, "%s" LINE_ENDING, cmdstr) < 0) { virReportOOMError(); goto cleanup; } msg.txLength = strlen(msg.txBuffer); VIR_DEBUG("Send command '%s' for write, seconds = %d", cmdstr, seconds); ret = qemuAgentSend(mon, &msg, seconds); VIR_DEBUG("Receive command reply ret=%d rxObject=%p", ret, msg.rxObject); if (ret == 0) { /* If we haven't obtained any reply but we wait for an * event, then don't report this as error */ if (!msg.rxObject) { if (await_event) { VIR_DEBUG("Woken up by event %d", await_event); } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing monitor reply object")); ret = -1; } } else { *reply = msg.rxObject; } } cleanup: VIR_FREE(cmdstr); VIR_FREE(msg.txBuffer); return ret; }
static int qemuAgentCheckError(virJSONValuePtr cmd, virJSONValuePtr reply) { if (virJSONValueObjectHasKey(reply, "error")) { virJSONValuePtr error = virJSONValueObjectGet(reply, "error"); char *cmdstr = virJSONValueToString(cmd, false); char *replystr = virJSONValueToString(reply, false); /* Log the full JSON formatted command & error */ VIR_DEBUG("unable to execute QEMU command %s: %s", cmdstr, replystr); /* Only send the user the command name + friendly error */ if (!error) virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to execute QEMU command '%s'"), qemuAgentCommandName(cmd)); else virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to execute QEMU command '%s': %s"), qemuAgentCommandName(cmd), qemuAgentStringifyError(error)); VIR_FREE(cmdstr); VIR_FREE(replystr); return -1; } else if (!virJSONValueObjectHasKey(reply, "return")) { char *cmdstr = virJSONValueToString(cmd, false); char *replystr = virJSONValueToString(reply, false); VIR_DEBUG("Neither 'return' nor 'error' is set in the JSON reply %s: %s", cmdstr, replystr); virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to execute QEMU command '%s'"), qemuAgentCommandName(cmd)); VIR_FREE(cmdstr); VIR_FREE(replystr); return -1; } return 0; }
static int testJSONDeflatten(const void *data) { const struct testInfo *info = data; virJSONValuePtr injson = NULL; virJSONValuePtr deflattened = NULL; char *infile = NULL; char *indata = NULL; char *outfile = NULL; char *actual = NULL; int ret = -1; if (virAsprintf(&infile, "%s/virjsondata/deflatten-%s-in.json", abs_srcdir, info->name) < 0 || virAsprintf(&outfile, "%s/virjsondata/deflatten-%s-out.json", abs_srcdir, info->name) < 0) goto cleanup; if (virTestLoadFile(infile, &indata) < 0) goto cleanup; if (!(injson = virJSONValueFromString(indata))) goto cleanup; if ((deflattened = virJSONValueObjectDeflatten(injson))) { if (!info->pass) { VIR_TEST_VERBOSE("%s: deflattening should have failed\n", info->name); goto cleanup; } } else { if (!info->pass) ret = 0; goto cleanup; } if (!(actual = virJSONValueToString(deflattened, true))) goto cleanup; if (virTestCompareToFile(actual, outfile) < 0) goto cleanup; ret = 0; cleanup: virJSONValueFree(injson); virJSONValueFree(deflattened); VIR_FREE(infile); VIR_FREE(indata); VIR_FREE(outfile); VIR_FREE(actual); return ret; }
static int qemuAgentCommand(qemuAgentPtr mon, virJSONValuePtr cmd, virJSONValuePtr *reply) { int ret = -1; qemuAgentMessage msg; char *cmdstr = NULL; *reply = NULL; if (qemuAgentGuestSync(mon) < 0) { /* helper reported the error */ return -1; } memset(&msg, 0, sizeof(msg)); if (!(cmdstr = virJSONValueToString(cmd))) { virReportOOMError(); goto cleanup; } if (virAsprintf(&msg.txBuffer, "%s" LINE_ENDING, cmdstr) < 0) { virReportOOMError(); goto cleanup; } msg.txLength = strlen(msg.txBuffer); VIR_DEBUG("Send command '%s' for write", cmdstr); ret = qemuAgentSend(mon, &msg, false); VIR_DEBUG("Receive command reply ret=%d rxObject=%p", ret, msg.rxObject); if (ret == 0) { if (!msg.rxObject) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing monitor reply object")); ret = -1; } else { *reply = msg.rxObject; } } cleanup: VIR_FREE(cmdstr); VIR_FREE(msg.txBuffer); return ret; }
static int testJSONFromString(const void *data) { const struct testInfo *info = data; virJSONValuePtr json; const char *expectstr = info->expect ? info->expect : info->doc; char *formatted = NULL; int ret = -1; json = virJSONValueFromString(info->doc); if (!json) { if (info->pass) { VIR_TEST_VERBOSE("Fail to parse %s\n", info->doc); goto cleanup; } else { VIR_TEST_DEBUG("Fail to parse %s\n", info->doc); ret = 0; goto cleanup; } } if (!info->pass) { VIR_TEST_VERBOSE("Should not have parsed %s\n", info->doc); goto cleanup; } VIR_TEST_DEBUG("Parsed %s\n", info->doc); if (!(formatted = virJSONValueToString(json, false))) { VIR_TEST_VERBOSE("Failed to format json data\n"); goto cleanup; } if (STRNEQ(expectstr, formatted)) { virTestDifference(stderr, expectstr, formatted); goto cleanup; } ret = 0; cleanup: VIR_FREE(formatted); virJSONValueFree(json); return ret; }
int qemuMonitorJSONIOProcessLine(qemuMonitorPtr mon, const char *line, qemuMonitorMessagePtr msg) { static bool first = true; virJSONValuePtr value = NULL; char *json = NULL; int ret; REAL_SYM(realQemuMonitorJSONIOProcessLine); ret = realQemuMonitorJSONIOProcessLine(mon, line, msg); if (ret == 0 && (value = virJSONValueFromString(line)) && (json = virJSONValueToString(value, 1))) { char *p; bool skip = false; if (first) first = false; else putchar('\n'); for (p = json; *p; p++) { if (skip && *p == '\n') { continue; } else { skip = *p == '\n'; putchar(*p); } } } VIR_FREE(json); virJSONValueFree(value); return ret; }
static int testQemuDiskXMLToPropsValidateFile(const void *opaque) { struct testQemuDiskXMLToJSONData *data = (void *) opaque; virBuffer buf = VIR_BUFFER_INITIALIZER; char *jsonpath = NULL; char *actual = NULL; int ret = -1; size_t i; if (data->fail) return EXIT_AM_SKIP; if (virAsprintf(&jsonpath, "%s%s.json", testQemuDiskXMLToJSONPath, data->name) < 0) goto cleanup; for (i = 0; i < data->nprops; i++) { char *jsonstr; if (!(jsonstr = virJSONValueToString(data->props[i], true))) goto cleanup; virBufferAdd(&buf, jsonstr, -1); VIR_FREE(jsonstr); } if (virBufferCheckError(&buf) < 0) goto cleanup; actual = virBufferContentAndReset(&buf); ret = virTestCompareToFile(actual, jsonpath); cleanup: VIR_FREE(jsonpath); VIR_FREE(actual); return ret; }
static char *testGenerateJSON(void) { virNetServerPtr srv = NULL; virJSONValuePtr json = NULL; char *jsonstr = NULL; bool has_ipv4, has_ipv6; /* Our pre-saved JSON file is created so that each service * only has one socket. If we let libvirt bind to IPv4 and * IPv6 we might end up with two sockets, so force one or * the other based on what's available on thehost */ if (virNetSocketCheckProtocols(&has_ipv4, &has_ipv6) < 0) return NULL; if (!has_ipv4 && !has_ipv6) return NULL; if (!(srv = testCreateServer( has_ipv4 ? "127.0.0.1" : "::1", has_ipv4 ? AF_INET : AF_INET6))) goto cleanup; if (!(json = virNetServerPreExecRestart(srv))) goto cleanup; if (!(jsonstr = virJSONValueToString(json, true))) goto cleanup; fprintf(stderr, "%s\n", jsonstr); cleanup: virNetServerClose(srv); virObjectUnref(srv); virJSONValueFree(json); return jsonstr; }
static int testJSONAddRemove(const void *data) { const struct testInfo *info = data; virJSONValuePtr json; virJSONValuePtr name = NULL; char *result = NULL; int ret = -1; json = virJSONValueFromString(info->doc); if (!json) { VIR_TEST_VERBOSE("Fail to parse %s\n", info->name); ret = -1; goto cleanup; } switch (virJSONValueObjectRemoveKey(json, "name", &name)) { case 1: if (!info->pass) { VIR_TEST_VERBOSE("should not remove from non-object %s\n", info->name); goto cleanup; } break; case -1: if (!info->pass) ret = 0; else VIR_TEST_VERBOSE("Fail to recognize non-object %s\n", info->name); goto cleanup; default: VIR_TEST_VERBOSE("unexpected result when removing from %s\n", info->name); goto cleanup; } if (STRNEQ_NULLABLE(virJSONValueGetString(name), "sample")) { VIR_TEST_VERBOSE("unexpected value after removing name: %s\n", NULLSTR(virJSONValueGetString(name))); goto cleanup; } if (virJSONValueObjectRemoveKey(json, "name", NULL)) { VIR_TEST_VERBOSE("%s", "unexpected success when removing missing key\n"); goto cleanup; } if (virJSONValueObjectAppendString(json, "newname", "foo") < 0) { VIR_TEST_VERBOSE("%s", "unexpected failure adding new key\n"); goto cleanup; } if (!(result = virJSONValueToString(json, false))) { VIR_TEST_VERBOSE("%s", "failed to stringize result\n"); goto cleanup; } if (STRNEQ(info->expect, result)) { virTestDifference(stderr, info->expect, result); goto cleanup; } ret = 0; cleanup: virJSONValueFree(json); virJSONValueFree(name); VIR_FREE(result); return ret; }
static int testJSONCopy(const void *data) { const struct testInfo *info = data; virJSONValuePtr json = NULL; virJSONValuePtr jsonCopy = NULL; char *result = NULL; char *resultCopy = NULL; int ret = -1; json = virJSONValueFromString(info->doc); if (!json) { VIR_TEST_VERBOSE("Failed to parse %s\n", info->doc); goto cleanup; } jsonCopy = virJSONValueCopy(json); if (!jsonCopy) { VIR_TEST_VERBOSE("Failed to copy JSON data\n"); goto cleanup; } result = virJSONValueToString(json, false); if (!result) { VIR_TEST_VERBOSE("Failed to format original JSON data\n"); goto cleanup; } resultCopy = virJSONValueToString(json, false); if (!resultCopy) { VIR_TEST_VERBOSE("Failed to format copied JSON data\n"); goto cleanup; } if (STRNEQ(result, resultCopy)) { if (virTestGetVerbose()) virTestDifference(stderr, result, resultCopy); goto cleanup; } VIR_FREE(result); VIR_FREE(resultCopy); result = virJSONValueToString(json, true); if (!result) { VIR_TEST_VERBOSE("Failed to format original JSON data\n"); goto cleanup; } resultCopy = virJSONValueToString(json, true); if (!resultCopy) { VIR_TEST_VERBOSE("Failed to format copied JSON data\n"); goto cleanup; } if (STRNEQ(result, resultCopy)) { if (virTestGetVerbose()) virTestDifference(stderr, result, resultCopy); goto cleanup; } ret = 0; cleanup: VIR_FREE(result); VIR_FREE(resultCopy); virJSONValueFree(json); virJSONValueFree(jsonCopy); return ret; }
static int testJSONLookup(const void *data) { const struct testInfo *info = data; virJSONValuePtr json; virJSONValuePtr value = NULL; char *result = NULL; int rc; int number; const char *str; int ret = -1; json = virJSONValueFromString(info->doc); if (!json) { VIR_TEST_VERBOSE("Fail to parse %s\n", info->doc); ret = -1; goto cleanup; } value = virJSONValueObjectGetObject(json, "a"); if (value) { if (!info->pass) { VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have failed\n", info->doc); goto cleanup; } else { result = virJSONValueToString(value, false); if (STRNEQ_NULLABLE(result, "{}")) { VIR_TEST_VERBOSE("lookup for 'a' in '%s' found '%s' but " "should have found '{}'\n", info->doc, NULLSTR(result)); goto cleanup; } VIR_FREE(result); } } else if (info->pass) { VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have succeeded\n", info->doc); goto cleanup; } number = 2; rc = virJSONValueObjectGetNumberInt(json, "b", &number); if (rc == 0) { if (!info->pass) { VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have failed\n", info->doc); goto cleanup; } else if (number != 1) { VIR_TEST_VERBOSE("lookup for 'b' in '%s' found %d but " "should have found 1\n", info->doc, number); goto cleanup; } } else if (info->pass) { VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have succeeded\n", info->doc); goto cleanup; } str = virJSONValueObjectGetString(json, "c"); if (str) { if (!info->pass) { VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have failed\n", info->doc); goto cleanup; } else if (STRNEQ(str, "str")) { VIR_TEST_VERBOSE("lookup for 'c' in '%s' found '%s' but " "should have found 'str'\n", info->doc, str); goto cleanup; } } else if (info->pass) { VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have succeeded\n", info->doc); goto cleanup; } value = virJSONValueObjectGetArray(json, "d"); if (value) { if (!info->pass) { VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have failed\n", info->doc); goto cleanup; } else { result = virJSONValueToString(value, false); if (STRNEQ_NULLABLE(result, "[]")) { VIR_TEST_VERBOSE("lookup for 'd' in '%s' found '%s' but " "should have found '[]'\n", info->doc, NULLSTR(result)); goto cleanup; } VIR_FREE(result); } } else if (info->pass) { VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have succeeded\n", info->doc); goto cleanup; } ret = 0; cleanup: virJSONValueFree(json); VIR_FREE(result); return ret; }
static int testExecRestart(const void *opaque) { int ret = -1; virNetServerPtr srv = NULL; const struct testExecRestartData *data = opaque; char *infile = NULL, *outfile = NULL; char *injsonstr = NULL, *outjsonstr = NULL; virJSONValuePtr injson = NULL, outjson = NULL; int fdclient[2] = { -1, -1 }, fdserver[2] = { -1, -1 }; if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdclient) < 0) { virReportSystemError(errno, "%s", "Cannot create socket pair"); goto cleanup; } if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdserver) < 0) { virReportSystemError(errno, "%s", "Cannot create socket pair"); goto cleanup; } /* We're blindly assuming the test case isn't using * fds 100->103 for something else, which is probably * fairly reasonable in general */ dup2(fdserver[0], 100); dup2(fdserver[1], 101); dup2(fdclient[0], 102); dup2(fdclient[1], 103); if (virAsprintf(&infile, "%s/virnetserverdata/input-data-%s.json", abs_srcdir, data->jsonfile) < 0) goto cleanup; if (virAsprintf(&outfile, "%s/virnetserverdata/output-data-%s.json", abs_srcdir, data->jsonfile) < 0) goto cleanup; if (virFileReadAll(infile, 8192, &injsonstr) < 0) goto cleanup; if (!(injson = virJSONValueFromString(injsonstr))) goto cleanup; if (!(srv = virNetServerNewPostExecRestart(injson, NULL, NULL, NULL, NULL, NULL))) goto cleanup; if (!(outjson = virNetServerPreExecRestart(srv))) goto cleanup; if (!(outjsonstr = virJSONValueToString(outjson, true))) goto cleanup; if (virtTestCompareToFile(outjsonstr, outfile) < 0) goto fail; ret = 0; cleanup: if (ret < 0) { virErrorPtr err = virGetLastError(); /* Rather be safe, we have lot of missing errors */ if (err) fprintf(stderr, "%s\n", err->message); else fprintf(stderr, "%s\n", "Unknown error"); } fail: VIR_FREE(infile); VIR_FREE(outfile); VIR_FREE(injsonstr); VIR_FREE(outjsonstr); virJSONValueFree(injson); virJSONValueFree(outjson); virObjectUnref(srv); VIR_FORCE_CLOSE(fdserver[0]); VIR_FORCE_CLOSE(fdserver[1]); VIR_FORCE_CLOSE(fdclient[0]); VIR_FORCE_CLOSE(fdclient[1]); return ret; }
static int testBackingXMLjsonXML(const void *args) { const struct testBackingXMLjsonXMLdata *data = args; VIR_AUTOPTR(xmlDoc) xml = NULL; VIR_AUTOPTR(xmlXPathContext) ctxt = NULL; VIR_AUTOCLEAN(virBuffer) buf = VIR_BUFFER_INITIALIZER; VIR_AUTOPTR(virJSONValue) backendprops = NULL; VIR_AUTOPTR(virJSONValue) wrapper = NULL; VIR_AUTOFREE(char *) propsstr = NULL; VIR_AUTOFREE(char *) protocolwrapper = NULL; VIR_AUTOFREE(char *) actualxml = NULL; VIR_AUTOUNREF(virStorageSourcePtr) xmlsrc = NULL; VIR_AUTOUNREF(virStorageSourcePtr) jsonsrc = NULL; if (!(xmlsrc = virStorageSourceNew())) return -1; xmlsrc->type = data->type; if (!(xml = virXMLParseStringCtxt(data->xml, "(test storage source XML)", &ctxt))) return -1; if (virDomainStorageSourceParse(ctxt->node, ctxt, xmlsrc, 0, NULL) < 0) { fprintf(stderr, "failed to parse disk source xml\n"); return -1; } if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true))) { fprintf(stderr, "failed to format disk source json\n"); return -1; } if (virJSONValueObjectCreate(&wrapper, "a:file", &backendprops, NULL) < 0) return -1; if (!(propsstr = virJSONValueToString(wrapper, false))) return -1; if (virAsprintf(&protocolwrapper, "json:%s", propsstr) < 0) return -1; if (!(jsonsrc = virStorageSourceNewFromBackingAbsolute(protocolwrapper))) { fprintf(stderr, "failed to parse disk json\n"); return -1; } if (virDomainDiskSourceFormat(&buf, jsonsrc, 0, false, 0, NULL) < 0 || !(actualxml = virBufferContentAndReset(&buf))) { fprintf(stderr, "failed to format disk source xml\n"); return -1; } if (STRNEQ(actualxml, data->xml)) { fprintf(stderr, "\n expected storage source xml:\n'%s'\n" "actual storage source xml:\n%s\n" "intermediate json:\n%s\n", data->xml, actualxml, protocolwrapper); return -1; } return 0; }