From e2ea0c38667cfdc0667322cb1beba95a6d677816 Mon Sep 17 00:00:00 2001
From: Jeffrey Cody <jcody@redhat.com>
Date: Tue, 20 Mar 2012 14:07:26 -0300
Subject: [RHEL6 qemu-kvm PATCH 06/21] monitor: Allow '-' and 'b' boolean types to be either bool or int.

RH-Author: Jeffrey Cody <jcody@redhat.com>
Message-id: <091b48565f06c5fab389a4acc06921e2c5c932e4.1332249823.git.jcody@redhat.com>
Patchwork-id: 38630
O-Subject: [RHEL6.3 qemu-kvm PATCH v3 06/21] monitor: Allow '-' and 'b' boolean types to be either bool or int.
Bugzilla: 784153
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Markus Armbruster <armbru@redhat.com>

In RHEL6, there are situations that could occur where a version of
libvirt that uses json-int for boolean types may be talking with QEMU.
This is a problem, because QEMU in RHEL follows the upstream change
of only allowing json-bool arguments for boolean types.

In order to not break compatibility, this patch makes it so QEMU
accepts either json-bool or json-int values for '-' boolean arguments.

This patch introduces another function in qdict called
'qdict_get_try_bool_or_int', which behaves the same as
'qdict_get_try_bool', except that it will try first a QBOOL, and then
a QINT type before resorting to the def_value fallback return.

The following commands had an argument with a boolean type (either
'b' or '-'):
     eject ('-'),
     migrate ('-'),
     set_link ('b')

Each of those handlers were changed from the qdict_get_.*bool()
functions for the boolean arguments, to the qdict_get_try_bool_or_int().

This is a RHEL-only patch, as it is not applicable upstream.

Signed-off-by: Jeff Cody <jcody@redhat.com>
---
 blockdev.c  |    2 +-
 migration.c |    6 +++---
 monitor.c   |    3 ++-
 net.c       |    2 +-
 qdict.c     |   21 +++++++++++++++++++++
 qdict.h     |    1 +
 6 files changed, 29 insertions(+), 6 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 blockdev.c  |    2 +-
 migration.c |    6 +++---
 monitor.c   |    3 ++-
 net.c       |    2 +-
 qdict.c     |   21 +++++++++++++++++++++
 qdict.h     |    1 +
 6 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index bf7d9af..10c4d34 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1010,7 +1010,7 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
 int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     BlockDriverState *bs;
-    int force = qdict_get_try_bool(qdict, "force", 0);
+    int force = qdict_get_try_bool_or_int(qdict, "force", 0);
     const char *filename = qdict_get_str(qdict, "device");
 
     bs = bdrv_find(filename);
diff --git a/migration.c b/migration.c
index 5a8059b..81f79fc 100644
--- a/migration.c
+++ b/migration.c
@@ -93,9 +93,9 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     MigrationState *s = NULL;
     const char *p;
-    int detach = qdict_get_try_bool(qdict, "detach", 0);
-    int blk = qdict_get_try_bool(qdict, "blk", 0);
-    int inc = qdict_get_try_bool(qdict, "inc", 0);
+    int detach = qdict_get_try_bool_or_int(qdict, "detach", 0);
+    int blk = qdict_get_try_bool_or_int(qdict, "blk", 0);
+    int inc = qdict_get_try_bool_or_int(qdict, "inc", 0);
     const char *uri = qdict_get_str(qdict, "uri");
 
     if (current_migration &&
diff --git a/monitor.c b/monitor.c
index 9f662b5..3ff955b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4483,7 +4483,8 @@ static int check_client_args_type(const QDict *client_args,
             break;
         case 'b':
         case '-':
-            if (qobject_type(client_arg) != QTYPE_QBOOL) {
+            if (qobject_type(client_arg) != QTYPE_QBOOL &&
+                qobject_type(client_arg) != QTYPE_QINT ) {
                 qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
                               "bool");
                return -1; 
diff --git a/net.c b/net.c
index a0a4b90..e10e085 100644
--- a/net.c
+++ b/net.c
@@ -1303,7 +1303,7 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
     VLANState *vlan;
     VLANClientState *vc = NULL;
     const char *name = qdict_get_str(qdict, "name");
-    int up = qdict_get_bool(qdict, "up");
+    int up = qdict_get_try_bool_or_int(qdict, "up", 0);
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
diff --git a/qdict.c b/qdict.c
index ae40b93..9b84bf5 100644
--- a/qdict.c
+++ b/qdict.c
@@ -326,6 +326,27 @@ int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value)
 }
 
 /**
+ * qdict_get_try_bool_or_int(): Try to get a bool or int mapped by 'key'
+ *
+ * Return bool or int mapped by 'key', if it is not present in the
+ * dictionary or if the stored object is not of QBool or QInt type
+ * 'def_value' will be returned.
+ */
+int qdict_get_try_bool_or_int(const QDict *qdict, const char *key, int def_value)
+{
+    QObject *obj;
+
+    obj = qdict_get(qdict, key);
+
+    if (obj && qobject_type(obj) == QTYPE_QBOOL) {
+        return qbool_get_int(qobject_to_qbool(obj));
+    } else if (obj && qobject_type(obj) == QTYPE_QINT) {
+        return qint_get_int(qobject_to_qint(obj));
+    }
+    return def_value;
+}
+
+/**
  * qdict_get_try_str(): Try to get a pointer to the stored string
  * mapped by 'key'
  *
diff --git a/qdict.h b/qdict.h
index f4c1791..97611cb 100644
--- a/qdict.h
+++ b/qdict.h
@@ -50,6 +50,7 @@ const char *qdict_get_str(const QDict *qdict, const char *key);
 int64_t qdict_get_try_int(const QDict *qdict, const char *key,
                           int64_t def_value);
 int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value);
+int qdict_get_try_bool_or_int(const QDict *qdict, const char *key, int def_value);
 const char *qdict_get_try_str(const QDict *qdict, const char *key);
 
 #endif /* QDICT_H */
-- 
1.7.3.2

