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