From eb9906468f6ac3bd5925c6caf7020a6063125672 Mon Sep 17 00:00:00 2001 From: Stefan Kober Date: Thu, 4 Sep 2025 14:10:27 +0200 Subject: [PATCH] ch: add/use virCHMonitorPut function This allows users to call API endpoints that require passing data in a generic way. Previously, only virCHMonitorPutNoContent was offered. On-behalf-of: SAP stefan.kober@sap.com Signed-off-by: Stefan Kober Signed-off-by: Michal Privoznik Reviewed-by: Michal Privoznik --- src/ch/ch_monitor.c | 54 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c index 89cd230053..a16d29979f 100644 --- a/src/ch/ch_monitor.c +++ b/src/ch/ch_monitor.c @@ -62,6 +62,12 @@ VIR_ONCE_GLOBAL_INIT(virCHMonitor); int virCHMonitorShutdownVMM(virCHMonitor *mon); int virCHMonitorPutNoContent(virCHMonitor *mon, const char *endpoint, domainLogContext *logCtxt); +static int +virCHMonitorPut(virCHMonitor *mon, + const char *endpoint, + virJSONValue *payload, + domainLogContext *logCtxt, + virJSONValue **answer); static int virCHMonitorBuildCPUJson(virJSONValue *content, virDomainDef *vmdef) @@ -868,12 +874,16 @@ curl_callback(void *contents, size_t size, size_t nmemb, void *userp) return content_size; } -int -virCHMonitorPutNoContent(virCHMonitor *mon, const char *endpoint, - domainLogContext *logCtxt) +static int +virCHMonitorPut(virCHMonitor *mon, + const char *endpoint, + virJSONValue *payload, + domainLogContext *logCtxt, + virJSONValue **answer) { VIR_LOCK_GUARD lock = virObjectLockGuard(mon); g_autofree char *url = NULL; + g_autofree char *payload_str = NULL; int responseCode = 0; int ret = -1; struct curl_data data = {0}; @@ -891,28 +901,56 @@ virCHMonitorPutNoContent(virCHMonitor *mon, const char *endpoint, curl_easy_setopt(mon->handle, CURLOPT_INFILESIZE, 0L); headers = curl_slist_append(headers, "Accept: application/json"); + curl_easy_setopt(mon->handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(mon->handle, CURLOPT_WRITEFUNCTION, curl_callback); curl_easy_setopt(mon->handle, CURLOPT_WRITEDATA, (void *)&data); + if (payload) { + payload_str = virJSONValueToString(payload, false); + curl_easy_setopt(mon->handle, CURLOPT_POSTFIELDS, payload_str); + curl_easy_setopt(mon->handle, CURLOPT_CUSTOMREQUEST, "PUT"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + } + responseCode = virCHMonitorCurlPerform(mon->handle); + data.content = g_realloc(data.content, data.size + 1); + data.content[data.size] = '\0'; + if (logCtxt && data.size) { /* Do this to append a NULL char at the end of data */ - data.content = g_realloc(data.content, data.size + 1); - data.content[data.size] = 0; domainLogContextWrite(logCtxt, "HTTP response code from CH: %d\n", responseCode); domainLogContextWrite(logCtxt, "Response = %s\n", data.content); } - if (responseCode == 200 || responseCode == 204) - ret = 0; + if (responseCode != 200 && responseCode != 204) { + ret = -1; + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid HTTP response code from CH: %1$d"), + responseCode); + goto cleanup; + } - curl_slist_free_all(headers); + if (answer) + *answer = virJSONValueFromString(data.content); + ret = 0; + + cleanup: + curl_slist_free_all(headers); + g_free(data.content); return ret; } +int +virCHMonitorPutNoContent(virCHMonitor *mon, + const char *endpoint, + domainLogContext *logCtxt) +{ + return virCHMonitorPut(mon, endpoint, NULL, logCtxt, NULL); +} + static int virCHMonitorGet(virCHMonitor *mon, const char *endpoint, virJSONValue **response) { -- 2.47.3