[libvirt] [PATCH 3/4] Update QEMU device_add command in JSON mode

Daniel P. Berrange berrange at redhat.com
Thu Apr 15 10:43:10 UTC 2010


The device_add command was added in JSON mode in a way I didn't
expect. Instead of passing the normal device string to the JSON
command:

    { "execute": "device_add", "arguments": { "device": "ne2k_pci,id=nic.1,netdev=net.1" } }

We need to split up the device string into a full JSON object

    { "execute": "device_add", "arguments": { "driver": "ne2k_pci", "id": "nic.1", "netdev": "net.1" } }

* src/qemu/qemu_conf.h, src/qemu/qemu_conf.c: Rename the
  qemuCommandLineParseKeywords method to qemuParseKeywords
  and export it to monitor
* src/qemu/qemu_monitor_json.c: Split up device string into
  a JSON object for device_add command
---
 src/qemu/qemu_conf.c         |   30 ++++++++--------
 src/qemu/qemu_conf.h         |    6 +++
 src/qemu/qemu_monitor_json.c |   78 +++++++++++++++++++++++++++++++++++++++--
 3 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 48252a5..5b5cdb0 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -4769,11 +4769,11 @@ static const char *qemuFindEnv(const char **progenv,
  * the "=value" part is optional and if a key with no value is found,
  * NULL is be placed into corresponding place in retvalues.
  */
-static int
-qemuParseCommandLineKeywords(const char *str,
-                             char ***retkeywords,
-                             char ***retvalues,
-                             int allowEmptyValue)
+int
+qemuParseKeywords(const char *str,
+                  char ***retkeywords,
+                  char ***retvalues,
+                  int allowEmptyValue)
 {
     int keywordCount = 0;
     int keywordAlloc = 0;
@@ -4872,9 +4872,9 @@ qemuParseCommandLineDisk(const char *val,
     int busid = -1;
     int unitid = -1;
 
-    if ((nkeywords = qemuParseCommandLineKeywords(val,
-                                                  &keywords,
-                                                  &values, 0)) < 0)
+    if ((nkeywords = qemuParseKeywords(val,
+                                       &keywords,
+                                       &values, 0)) < 0)
         return NULL;
 
     if (VIR_ALLOC(def) < 0) {
@@ -5112,9 +5112,9 @@ qemuParseCommandLineNet(virCapsPtr caps,
     tmp = strchr(val, ',');
 
     if (tmp) {
-        if ((nkeywords = qemuParseCommandLineKeywords(tmp+1,
-                                                      &keywords,
-                                                      &values, 0)) < 0)
+        if ((nkeywords = qemuParseKeywords(tmp+1,
+                                           &keywords,
+                                           &values, 0)) < 0)
             return NULL;
     } else {
         nkeywords = 0;
@@ -5184,9 +5184,9 @@ qemuParseCommandLineNet(virCapsPtr caps,
     VIR_FREE(values);
 
     if (STRPREFIX(nic, "nic,")) {
-        if ((nkeywords = qemuParseCommandLineKeywords(nic + strlen("nic,"),
-                                                      &keywords,
-                                                      &values, 0)) < 0) {
+        if ((nkeywords = qemuParseKeywords(nic + strlen("nic,"),
+                                           &keywords,
+                                           &values, 0)) < 0) {
             virDomainNetDefFree(def);
             def = NULL;
             goto cleanup;
@@ -5594,7 +5594,7 @@ qemuParseCommandLineSmp(virDomainDefPtr dom,
     char *end;
     int ret;
 
-    nkws = qemuParseCommandLineKeywords(val, &kws, &vals, 1);
+    nkws = qemuParseKeywords(val, &kws, &vals, 1);
     if (nkws < 0)
         return -1;
 
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index e0666cb..574709e 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -311,5 +311,11 @@ int qemuAssignDeviceDiskAlias(virDomainDiskDefPtr def, unsigned long long qemuCm
 int qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr net, int idx);
 int qemuAssignDeviceControllerAlias(virDomainControllerDefPtr controller);
 
+int
+qemuParseKeywords(const char *str,
+                  char ***retkeywords,
+                  char ***retvalues,
+                  int allowEmptyValue);
+
 
 #endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 6c73685..3b97d05 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1846,24 +1846,94 @@ int qemuMonitorJSONDelDevice(qemuMonitorPtr mon,
 }
 
 
+static void
+qemuFreeKeywords(int nkeywords, char **keywords, char **values)
+{
+    int i;
+    for (i = 0 ; i < nkeywords ; i++) {
+        VIR_FREE(keywords[i]);
+        VIR_FREE(values[i]);
+    }
+    VIR_FREE(keywords);
+    VIR_FREE(values);
+}
+
+static virJSONValuePtr
+qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword)
+{
+    virJSONValuePtr ret = NULL;
+    char **keywords = NULL;
+    char **values = NULL;
+    int nkeywords = 0;
+    int i;
+
+    if (!(ret = virJSONValueNewObject()))
+        goto no_memory;
+
+    nkeywords = qemuParseKeywords(str, &keywords, &values, 1);
+
+    if (nkeywords < 0)
+        goto error;
+
+    for (i = 0 ; i < nkeywords ; i++) {
+        if (values[i] == NULL) {
+            if (i != 0) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("unexpected empty keyword in %s"), str);
+                goto error;
+            } else {
+                /* This 3rd arg isn't a typo - the way the parser works is
+                 * that the value ended up in the keyword field */
+                if (virJSONValueObjectAppendString(ret, firstkeyword, keywords[i]) < 0)
+                    goto no_memory;
+            }
+        } else {
+            if (virJSONValueObjectAppendString(ret, keywords[i], values[i]) < 0)
+                goto no_memory;
+        }
+    }
+
+    qemuFreeKeywords(nkeywords, keywords, values);
+    return ret;
+
+no_memory:
+    virReportOOMError();
+error:
+    qemuFreeKeywords(nkeywords, keywords, values);
+    virJSONValueFree(ret);
+    return NULL;
+}
+
+
 int qemuMonitorJSONAddDevice(qemuMonitorPtr mon,
                              const char *devicestr)
 {
-    int ret;
+    int ret = -1;
     virJSONValuePtr cmd;
     virJSONValuePtr reply = NULL;
+    virJSONValuePtr args;
 
-    cmd = qemuMonitorJSONMakeCommand("device_add",
-                                     "s:config", devicestr,
-                                     NULL);
+    cmd = qemuMonitorJSONMakeCommand("device_add", NULL);
     if (!cmd)
         return -1;
 
+    args = qemuMonitorJSONKeywordStringToJSON(devicestr, "driver");
+    if (!args)
+        goto cleanup;
+
+    if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    args = NULL; /* obj owns reference to args now */
+
     ret = qemuMonitorJSONCommand(mon, cmd, &reply);
 
     if (ret == 0)
         ret = qemuMonitorJSONCheckError(cmd, reply);
 
+cleanup:
+    virJSONValueFree(args);
     virJSONValueFree(cmd);
     virJSONValueFree(reply);
     return ret;
-- 
1.6.6.1




More information about the libvir-list mailing list