mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
qemu: chardev: Extract more information about character devices
Improve the monitor function to also retrieve the guest state of character device (if provided) so that we can refresh the state of virtio-serial channels and perhaps react to changes in the state in future patches. This patch changes the returned data from qemuMonitorGetChardevInfo to return a structure containing the pty path and the state for all the character devices. The change to the testsuite makes sure that the data is parsed correctly.
This commit is contained in:
parent
42874fa45f
commit
4d7eb90311
@ -2982,6 +2982,17 @@ qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuMonitorChardevInfoFree(void *data,
|
||||
const void *name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
qemuMonitorChardevInfoPtr info = data;
|
||||
|
||||
VIR_FREE(info->ptyPath);
|
||||
VIR_FREE(info);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
|
||||
virHashTablePtr *retinfo)
|
||||
@ -2997,7 +3008,7 @@ qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(info = virHashCreate(10, virHashValueFree)))
|
||||
if (!(info = virHashCreate(10, qemuMonitorChardevInfoFree)))
|
||||
goto error;
|
||||
|
||||
if (mon->json)
|
||||
|
@ -649,6 +649,12 @@ int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
|
||||
int qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
virNetDevRxFilterPtr *filter);
|
||||
|
||||
typedef struct _qemuMonitorChardevInfo qemuMonitorChardevInfo;
|
||||
typedef qemuMonitorChardevInfo *qemuMonitorChardevInfoPtr;
|
||||
struct _qemuMonitorChardevInfo {
|
||||
char *ptyPath;
|
||||
virDomainChrDeviceState state;
|
||||
};
|
||||
int qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
|
||||
virHashTablePtr *retinfo);
|
||||
|
||||
|
@ -3414,7 +3414,7 @@ qemuMonitorJSONQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
||||
*
|
||||
* {"return": [
|
||||
* {"filename": "stdio", "label": "monitor"},
|
||||
* {"filename": "pty:/dev/pts/6", "label": "serial0"},
|
||||
* {"filename": "pty:/dev/pts/6", "label": "serial0", "frontend-open": true},
|
||||
* {"filename": "pty:/dev/pts/7", "label": "parallel0"}
|
||||
* ]}
|
||||
*
|
||||
@ -3426,6 +3426,7 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
|
||||
virJSONValuePtr data;
|
||||
int ret = -1;
|
||||
size_t i;
|
||||
qemuMonitorChardevInfoPtr entry = NULL;
|
||||
|
||||
if (!(data = virJSONValueObjectGet(reply, "return"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
@ -3440,44 +3441,60 @@ qemuMonitorJSONExtractChardevInfo(virJSONValuePtr reply,
|
||||
}
|
||||
|
||||
for (i = 0; i < virJSONValueArraySize(data); i++) {
|
||||
virJSONValuePtr entry = virJSONValueArrayGet(data, i);
|
||||
virJSONValuePtr chardev = virJSONValueArrayGet(data, i);
|
||||
const char *type;
|
||||
const char *id;
|
||||
if (!entry) {
|
||||
const char *alias;
|
||||
bool connected;
|
||||
|
||||
if (!chardev) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("character device information was missing array element"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(type = virJSONValueObjectGetString(entry, "filename"))) {
|
||||
if (!(alias = virJSONValueObjectGetString(chardev, "label"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("character device information was missing label"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(type = virJSONValueObjectGetString(chardev, "filename"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("character device information was missing filename"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(id = virJSONValueObjectGetString(entry, "label"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("character device information was missing filename"));
|
||||
if (VIR_ALLOC(entry) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (STRPREFIX(type, "pty:") &&
|
||||
VIR_STRDUP(entry->ptyPath, type + strlen("pty:")) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virJSONValueObjectGetBoolean(chardev, "frontend-open", &connected) == 0) {
|
||||
if (connected)
|
||||
entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED;
|
||||
else
|
||||
entry->state = VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (STRPREFIX(type, "pty:")) {
|
||||
char *path;
|
||||
if (VIR_STRDUP(path, type + strlen("pty:")) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virHashAddEntry(info, id, path) < 0) {
|
||||
if (virHashAddEntry(info, alias, entry) < 0) {
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("failed to save chardev path '%s'"), path);
|
||||
VIR_FREE(path);
|
||||
_("failed to add chardev '%s' info"), alias);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
entry = NULL;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (entry) {
|
||||
VIR_FREE(entry->ptyPath);
|
||||
VIR_FREE(entry);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2174,6 +2174,7 @@ int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
|
||||
virHashTablePtr info)
|
||||
{
|
||||
char *reply = NULL;
|
||||
qemuMonitorChardevInfoPtr entry = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (qemuMonitorHMPCommand(mon, "info chardev", &reply) < 0)
|
||||
@ -2218,17 +2219,22 @@ int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
|
||||
|
||||
/* Path is everything after needle to the end of the line */
|
||||
*eol = '\0';
|
||||
char *path;
|
||||
if (VIR_STRDUP(path, needle + strlen(NEEDLE)) < 0)
|
||||
|
||||
if (VIR_ALLOC(entry) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virHashAddEntry(info, id, path) < 0) {
|
||||
if (VIR_STRDUP(entry->ptyPath, needle + strlen(NEEDLE)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virHashAddEntry(info, id, entry) < 0) {
|
||||
virReportError(VIR_ERR_OPERATION_FAILED,
|
||||
_("failed to save chardev path '%s'"),
|
||||
path);
|
||||
VIR_FREE(path);
|
||||
entry->ptyPath);
|
||||
VIR_FREE(entry->ptyPath);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
entry = NULL;
|
||||
#undef NEEDLE
|
||||
}
|
||||
|
||||
@ -2236,6 +2242,7 @@ int qemuMonitorTextGetChardevInfo(qemuMonitorPtr mon,
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(reply);
|
||||
VIR_FREE(entry);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1919,7 +1919,7 @@ qemuProcessLookupPTYs(virDomainDefPtr def,
|
||||
|
||||
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
|
||||
char id[32];
|
||||
const char *path;
|
||||
qemuMonitorChardevInfoPtr entry;
|
||||
|
||||
if (snprintf(id, sizeof(id), "%s%s",
|
||||
chardevfmt ? "char" : "",
|
||||
@ -1930,8 +1930,8 @@ qemuProcessLookupPTYs(virDomainDefPtr def,
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = (const char *) virHashLookup(info, id);
|
||||
if (path == NULL) {
|
||||
entry = virHashLookup(info, id);
|
||||
if (!entry || !entry->ptyPath) {
|
||||
if (chr->source.data.file.path == NULL) {
|
||||
/* neither the log output nor 'info chardev' had a
|
||||
* pty path for this chardev, report an error
|
||||
@ -1948,7 +1948,7 @@ qemuProcessLookupPTYs(virDomainDefPtr def,
|
||||
}
|
||||
|
||||
VIR_FREE(chr->source.data.file.path);
|
||||
if (VIR_STRDUP(chr->source.data.file.path, path) < 0)
|
||||
if (VIR_STRDUP(chr->source.data.file.path, entry->ptyPath) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1759,11 +1759,28 @@ testQemuMonitorJSONqemuMonitorJSONGetSpiceMigrationStatus(const void *data)
|
||||
}
|
||||
|
||||
static int
|
||||
testHashEqualString(const void *value1, const void *value2)
|
||||
testHashEqualChardevInfo(const void *value1, const void *value2)
|
||||
{
|
||||
return strcmp(value1, value2);
|
||||
const qemuMonitorChardevInfo *info1 = value1;
|
||||
const qemuMonitorChardevInfo *info2 = value2;
|
||||
|
||||
if (info1->state != info2->state)
|
||||
goto error;
|
||||
|
||||
if (STRNEQ_NULLABLE(info1->ptyPath, info2->ptyPath))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
fprintf(stderr, "\n"
|
||||
"info1->state: %d info2->state: %d\n"
|
||||
"info1->ptyPath: %s info2->ptyPath: %s\n",
|
||||
info1->state, info2->state, info1->ptyPath, info2->ptyPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
{
|
||||
@ -1771,6 +1788,10 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
|
||||
int ret = -1;
|
||||
virHashTablePtr info = NULL, expectedInfo = NULL;
|
||||
qemuMonitorChardevInfo info0 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
|
||||
qemuMonitorChardevInfo info1 = { (char *) "/dev/pts/21", VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED };
|
||||
qemuMonitorChardevInfo info2 = { (char *) "/dev/pts/20", VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
|
||||
qemuMonitorChardevInfo info3 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED };
|
||||
|
||||
if (!test)
|
||||
return -1;
|
||||
@ -1779,8 +1800,10 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
!(expectedInfo = virHashCreate(32, NULL)))
|
||||
goto cleanup;
|
||||
|
||||
if (virHashAddEntry(expectedInfo, "charserial1", (void *) "/dev/pts/21") < 0 ||
|
||||
virHashAddEntry(expectedInfo, "charserial0", (void *) "/dev/pts/20") < 0) {
|
||||
if (virHashAddEntry(expectedInfo, "charserial1", &info1) < 0 ||
|
||||
virHashAddEntry(expectedInfo, "charserial0", &info2) < 0 ||
|
||||
virHashAddEntry(expectedInfo, "charmonitor", &info0) < 0 ||
|
||||
virHashAddEntry(expectedInfo, "charserial2", &info3) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"Unable to create expectedInfo hash table");
|
||||
goto cleanup;
|
||||
@ -1791,7 +1814,8 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
" \"return\": ["
|
||||
" {"
|
||||
" \"filename\": \"pty:/dev/pts/21\","
|
||||
" \"label\": \"charserial1\""
|
||||
" \"label\": \"charserial1\","
|
||||
" \"frontend-open\": true"
|
||||
" },"
|
||||
" {"
|
||||
" \"filename\": \"pty:/dev/pts/20\","
|
||||
@ -1800,6 +1824,11 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
" {"
|
||||
" \"filename\": \"unix:/var/lib/libvirt/qemu/gentoo.monitor,server\","
|
||||
" \"label\": \"charmonitor\""
|
||||
" },"
|
||||
" {"
|
||||
" \"filename\": \"unix:/path/to/socket,server\","
|
||||
" \"label\": \"charserial2\","
|
||||
" \"frontend-open\": false"
|
||||
" }"
|
||||
" ],"
|
||||
" \"id\": \"libvirt-15\""
|
||||
@ -1810,7 +1839,7 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
info) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!virHashEqual(info, expectedInfo, testHashEqualString)) {
|
||||
if (!virHashEqual(info, expectedInfo, testHashEqualChardevInfo)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"Hashtable is different to the expected one");
|
||||
goto cleanup;
|
||||
|
Loading…
x
Reference in New Issue
Block a user