Patchwork [02/11] Add migrate-set-capabilities and query-migrate-capabilities

login
register
mail settings
Submitter Orit Wasserman
Date Aug. 5, 2012, 9:13 a.m.
Message ID <1344158004-10370-3-git-send-email-owasserm@redhat.com>
Download mbox | patch
Permalink /patch/175164/
State New
Headers show

Comments

Orit Wasserman - Aug. 5, 2012, 9:13 a.m.
The management can enable/disable a capability for the next migration by using
migrate-set-apabilities QMP command.
The management can query the current migration capabilities using
query-migrate-capabilities QMP command.
The user can use migrate_set_capability and 'info migrate_capabilities' HMP
commands.

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |   16 +++++++++++++
 hmp.c            |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hmp.h            |    2 +
 migration.c      |   46 ++++++++++++++++++++++++++++++++++++++
 migration.h      |    2 +
 monitor.c        |    7 +++++
 qapi-schema.json |   21 +++++++++++++++++
 qmp-commands.hx  |   49 ++++++++++++++++++++++++++++++++++++++++
 8 files changed, 208 insertions(+), 0 deletions(-)
Eric Blake - Aug. 6, 2012, 2:26 p.m.
On 08/05/2012 03:13 AM, Orit Wasserman wrote:
> The management can enable/disable a capability for the next migration by using
> migrate-set-apabilities QMP command.

s/set-apabilities/set-capabilities/

> The management can query the current migration capabilities using
> query-migrate-capabilities QMP command.
> The user can use migrate_set_capability and 'info migrate_capabilities' HMP
> commands.
> 
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---

> @@ -1419,6 +1433,8 @@ show user network stack connection states
>  show migration status
>  @item info migrate_supported_capabilities
>  show migrate supported capabilities
> +@item info migrate_capabilities
> +show current migration capabilities

In HMP, are migrate_supported_capabilities and migrate_capabilities
redundant?  That is, I think I can use either command to answer both
questions "what capabilities exist" and "what is the current state of
all capabilities that exist", since _both_ commands output a list of
capability names as well as an on/off designator.  If my analysis is
right, then we don't need migrate_supported_capabilities.

> +++ b/qapi-schema.json
> @@ -345,6 +345,27 @@
>  { 'command': 'query-migrate-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }

After all, in QMP, 'query-migrate-supported-capabilities'...

>  
>  ##
> +# @migrate-set-capabilities
> +#
> +# Enable/Disable the following migration capabilities (like xbzrle)
> +#

Missing a line, something like:

# @capabilities: json array of capability modifications to make

> +# Since: 1.2
> +##
> +{ 'command': 'migrate-set-capabilities',
> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
> +
> +##
> +# @query-migrate-capabilities
> +#
> +# Returns information about the current migration capabilities status
> +#
> +# Returns: @MigrationCapabilitiesStatus
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'query-migrate-capabilities', 'returns':   ['MigrationCapabilityStatus']}

...and 'query-migrate-capabilities' return the same information.  So we
don't need two commands, just one would do.

Spacing was awkward before that '['.

I would recommend that you s/[_-]supported// in patch 1/11, then removed
query-migrate-capabilities in 2/11 (having moved it to 1/11), leaving
2/11 to just focus on migrate-set-capabilities.
Orit Wasserman - Aug. 6, 2012, 4:04 p.m.
On 08/06/2012 05:26 PM, Eric Blake wrote:
> On 08/05/2012 03:13 AM, Orit Wasserman wrote:
>> The management can enable/disable a capability for the next migration by using
>> migrate-set-apabilities QMP command.
> 
> s/set-apabilities/set-capabilities/
> 
>> The management can query the current migration capabilities using
>> query-migrate-capabilities QMP command.
>> The user can use migrate_set_capability and 'info migrate_capabilities' HMP
>> commands.
>>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
> 
>> @@ -1419,6 +1433,8 @@ show user network stack connection states
>>  show migration status
>>  @item info migrate_supported_capabilities
>>  show migrate supported capabilities
>> +@item info migrate_capabilities
>> +show current migration capabilities
> 
> In HMP, are migrate_supported_capabilities and migrate_capabilities
> redundant?  That is, I think I can use either command to answer both
> questions "what capabilities exist" and "what is the current state of
> all capabilities that exist", since _both_ commands output a list of
> capability names as well as an on/off designator.  If my analysis is
> right, then we don't need migrate_supported_capabilities.
No 'info migrate_supported_capabilities' shows the capabilities this version of QEMU can supports.
and 'info migrate_capabilities' show what are the state of capabilities for the migration, i.e what is enabled.
> 
>> +++ b/qapi-schema.json
>> @@ -345,6 +345,27 @@
>>  { 'command': 'query-migrate-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
> 
> After all, in QMP, 'query-migrate-supported-capabilities'...
> 
>>  
>>  ##
>> +# @migrate-set-capabilities
>> +#
>> +# Enable/Disable the following migration capabilities (like xbzrle)
>> +#
> 
> Missing a line, something like:
> 
> # @capabilities: json array of capability modifications to make
> 
>> +# Since: 1.2
>> +##
>> +{ 'command': 'migrate-set-capabilities',
>> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
>> +
>> +##
>> +# @query-migrate-capabilities
>> +#
>> +# Returns information about the current migration capabilities status
>> +#
>> +# Returns: @MigrationCapabilitiesStatus
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'command': 'query-migrate-capabilities', 'returns':   ['MigrationCapabilityStatus']}
> 
> ...and 'query-migrate-capabilities' return the same information.  So we
> don't need two commands, just one would do.
> 
> Spacing was awkward before that '['.
> 
> I would recommend that you s/[_-]supported// in patch 1/11, then removed
> query-migrate-capabilities in 2/11 (having moved it to 1/11), leaving
> 2/11 to just focus on migrate-set-capabilities.
see above.
> 
Orit
Eric Blake - Aug. 6, 2012, 4:14 p.m.
On 08/06/2012 10:04 AM, Orit Wasserman wrote:
> On 08/06/2012 05:26 PM, Eric Blake wrote:
>> On 08/05/2012 03:13 AM, Orit Wasserman wrote:
>>> The management can enable/disable a capability for the next migration by using
>>> migrate-set-apabilities QMP command.
>>
>> s/set-apabilities/set-capabilities/
>>

>> In HMP, are migrate_supported_capabilities and migrate_capabilities
>> redundant?  That is, I think I can use either command to answer both
>> questions "what capabilities exist" and "what is the current state of
>> all capabilities that exist", since _both_ commands output a list of
>> capability names as well as an on/off designator.  If my analysis is
>> right, then we don't need migrate_supported_capabilities.
> No 'info migrate_supported_capabilities' shows the capabilities this version of QEMU can supports.
> and 'info migrate_capabilities' show what are the state of capabilities for the migration, i.e what is enabled.

Let's compare:

patch 1/11:

+void hmp_info_migrate_supported_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migrate_supported_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No supported migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");


patch 2/11:

+void hmp_info_migrate_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps, *cap;
+
+    caps = qmp_query_migrate_capabilities(NULL);
+
+    if (caps) {
+        monitor_printf(mon, "capabilities: ");
+        for (cap = caps; cap; cap = cap->next) {
+            monitor_printf(mon, "%s: %s ",
+
MigrationCapability_lookup[cap->value->capability],
+                           cap->value->state ? "on" : "off");

That is, BOTH commands end up iterating over a list of caps, and output
identical information in the case where caps exist of 'name: state' for
each capability.

They really ARE redundant - both commands are telling me:

capabilities:
xbzrle: on
foobar: off

which I can read to answer both my question of 'what is supported'
(xbzrle and foobar) and 'what is enabled' (xbzrle).  I see no need to
have to commands to tell me the same information, so I'd prefer the
shorter name.
Orit Wasserman - Aug. 6, 2012, 4:28 p.m.
On 08/06/2012 07:14 PM, Eric Blake wrote:
> On 08/06/2012 10:04 AM, Orit Wasserman wrote:
>> On 08/06/2012 05:26 PM, Eric Blake wrote:
>>> On 08/05/2012 03:13 AM, Orit Wasserman wrote:
>>>> The management can enable/disable a capability for the next migration by using
>>>> migrate-set-apabilities QMP command.
>>>
>>> s/set-apabilities/set-capabilities/
>>>
> 
>>> In HMP, are migrate_supported_capabilities and migrate_capabilities
>>> redundant?  That is, I think I can use either command to answer both
>>> questions "what capabilities exist" and "what is the current state of
>>> all capabilities that exist", since _both_ commands output a list of
>>> capability names as well as an on/off designator.  If my analysis is
>>> right, then we don't need migrate_supported_capabilities.
>> No 'info migrate_supported_capabilities' shows the capabilities this version of QEMU can supports.
>> and 'info migrate_capabilities' show what are the state of capabilities for the migration, i.e what is enabled.
> 
> Let's compare:
> 
> patch 1/11:
> 
> +void hmp_info_migrate_supported_capabilities(Monitor *mon)
> +{
> +    MigrationCapabilityStatusList *caps_list, *cap;
> +
> +    caps_list = qmp_query_migrate_supported_capabilities(NULL);
> +    if (!caps_list) {
> +        monitor_printf(mon, "No supported migration capabilities found\n");
> +        return;
> +    }
> +
> +    for (cap = caps_list; cap; cap = cap->next) {
> +        monitor_printf(mon, "%s: %s ",
> +                       MigrationCapability_lookup[cap->value->capability],
> +                       cap->value->state ? "on" : "off");
> 
> 
> patch 2/11:
> 
> +void hmp_info_migrate_capabilities(Monitor *mon)
> +{
> +    MigrationCapabilityStatusList *caps, *cap;
> +
> +    caps = qmp_query_migrate_capabilities(NULL);
> +
> +    if (caps) {
> +        monitor_printf(mon, "capabilities: ");
> +        for (cap = caps; cap; cap = cap->next) {
> +            monitor_printf(mon, "%s: %s ",
> +
> MigrationCapability_lookup[cap->value->capability],
> +                           cap->value->state ? "on" : "off");
> 
> That is, BOTH commands end up iterating over a list of caps, and output
> identical information in the case where caps exist of 'name: state' for
> each capability.
> 
> They really ARE redundant - both commands are telling me:
> 
> capabilities:
> xbzrle: on
> foobar: off
> 
> which I can read to answer both my question of 'what is supported'
> (xbzrle and foobar) and 'what is enabled' (xbzrle).  I see no need to
> have to commands to tell me the same information, so I'd prefer the
> shorter name.
> 
The information is different:
the first:
MigrationCapabilityStatusList *
qmp_query_migrate_supported_capabilities(Error **errp)
{
    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));

    caps_list->value = g_malloc(sizeof(*caps_list->value));
    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
    caps_list->value->state = true;
    caps_list->next = NULL;

    return caps_list;
}

the second:
MigrationCapabilityStatusList *
qmp_query_migrate_supported_capabilities(Error **errp)
{
    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));

    caps_list->value = g_malloc(sizeof(*caps_list->value));
    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
    caps_list->value->state = true;
    caps_list->next = NULL;

    return caps_list;
}

you can look at it as 64bit support one is to know if the processor supports 64 bit
the other to know if the OS uses 64 bit

Orit
Eric Blake - Aug. 6, 2012, 4:39 p.m.
On 08/06/2012 10:28 AM, Orit Wasserman wrote:

>> That is, BOTH commands end up iterating over a list of caps, and output
>> identical information in the case where caps exist of 'name: state' for
>> each capability.
>>

> The information is different:
> the first:
> MigrationCapabilityStatusList *
> qmp_query_migrate_supported_capabilities(Error **errp)
> {
>     MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
> 
>     caps_list->value = g_malloc(sizeof(*caps_list->value));
>     caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
>     caps_list->value->state = true;
>     caps_list->next = NULL;
> 
>     return caps_list;
> }
> 
> the second:
> MigrationCapabilityStatusList *
> qmp_query_migrate_supported_capabilities(Error **errp)

I think you meant this for the second:

+MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *head = NULL;
+    MigrationCapabilityStatusList *caps;
+    MigrationState *s = migrate_get_current();
+    int i;
+
+    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+        if (head == NULL) {
+            head = g_malloc0(sizeof(*caps));
+            caps = head;
+        } else {
+            caps->next = g_malloc0(sizeof(*caps));
+            caps = caps->next;
+        }
+        caps->value =
+            g_malloc(sizeof(*caps->value));
+        caps->value->capability = i;
+        caps->value->state = s->enabled_capabilities[i];
+    }

> you can look at it as 64bit support one is to know if the processor supports 64 bit
> the other to know if the OS uses 64 bit

Okay, so the QMP code is currently different (one outputs a list where
every entry in the list is hard-coded to true, the other outputs a list
where each entry reflects the current state).  But that still doesn't
address my concern that you don't need two QMP commands.

Merely listing 'xbzrle' in the list is enough to know that 'this
particular qemu knows how to do xbzrle', and the user is free to ignore
the additional information of whether it is actually in use at the time
if all the application cared about was determining the set of known
capabilities.

Given your argument with 64-bit processing, the same reasoning applies -
ask for a list of capabilities, and the result will either omit '64bit'
(the capability is not possible), include '64bit:false' (the capability
is known by the emulator, but not in use by the guest), or include
'64bit:true' (the capability is both known and in-use).  A user that
only cares about querying supported capabilities will check whether
'64bit' is in the list, and throw away the information about whether it
is on or off (and since the QMP command currently returns a hard-coded
true, that information is already being discarded via your
query-migrate-supported-capabilities command).  That is, your
implementation for query-migrate-capabilities is sufficient to satisfy
both class of users, without needing query-migrate-supported-capabilities.
Orit Wasserman - Aug. 6, 2012, 4:49 p.m.
On 08/06/2012 07:39 PM, Eric Blake wrote:
> On 08/06/2012 10:28 AM, Orit Wasserman wrote:
> 
>>> That is, BOTH commands end up iterating over a list of caps, and output
>>> identical information in the case where caps exist of 'name: state' for
>>> each capability.
>>>
> 
>> The information is different:
>> the first:
>> MigrationCapabilityStatusList *
>> qmp_query_migrate_supported_capabilities(Error **errp)
>> {
>>     MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
>>
>>     caps_list->value = g_malloc(sizeof(*caps_list->value));
>>     caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
>>     caps_list->value->state = true;
>>     caps_list->next = NULL;
>>
>>     return caps_list;
>> }
>>
>> the second:
>> MigrationCapabilityStatusList *
>> qmp_query_migrate_supported_capabilities(Error **errp)
> 
> I think you meant this for the second:
> 
> +MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
> +{
> +    MigrationCapabilityStatusList *head = NULL;
> +    MigrationCapabilityStatusList *caps;
> +    MigrationState *s = migrate_get_current();
> +    int i;
> +
> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> +        if (head == NULL) {
> +            head = g_malloc0(sizeof(*caps));
> +            caps = head;
> +        } else {
> +            caps->next = g_malloc0(sizeof(*caps));
> +            caps = caps->next;
> +        }
> +        caps->value =
> +            g_malloc(sizeof(*caps->value));
> +        caps->value->capability = i;
> +        caps->value->state = s->enabled_capabilities[i];
> +    }
> 
>> you can look at it as 64bit support one is to know if the processor supports 64 bit
>> the other to know if the OS uses 64 bit
> 
> Okay, so the QMP code is currently different (one outputs a list where
> every entry in the list is hard-coded to true, the other outputs a list
> where each entry reflects the current state).  But that still doesn't
> address my concern that you don't need two QMP commands.
> 
> Merely listing 'xbzrle' in the list is enough to know that 'this
> particular qemu knows how to do xbzrle', and the user is free to ignore
> the additional information of whether it is actually in use at the time
> if all the application cared about was determining the set of known
> capabilities.
> 
> Given your argument with 64-bit processing, the same reasoning applies -
> ask for a list of capabilities, and the result will either omit '64bit'
> (the capability is not possible), include '64bit:false' (the capability
> is known by the emulator, but not in use by the guest), or include
> '64bit:true' (the capability is both known and in-use).  A user that
> only cares about querying supported capabilities will check whether
> '64bit' is in the list, and throw away the information about whether it
> is on or off (and since the QMP command currently returns a hard-coded
> true, that information is already being discarded via your
> query-migrate-supported-capabilities command).  That is, your
> implementation for query-migrate-capabilities is sufficient to satisfy
> both class of users, without needing query-migrate-supported-capabilities.
> 
As you represent the user (libvirt) you know the best.
I will remove supported-capabilities commands.

Orit

Patch

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 1aa314f..9a2b987 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -861,6 +861,20 @@  Set maximum tolerated downtime (in seconds) for migration.
 ETEXI
 
     {
+        .name       = "migrate_set_capability",
+        .args_type  = "capability:s,state:b",
+        .params     = "capability state",
+        .help       = "Enable/Disable the usage of a capability for migration",
+        .mhandler.cmd = hmp_migrate_set_capability,
+    },
+
+STEXI
+@item migrate_set_capability @var{capability} @var{state}
+@findex migrate_set_capability
+Enable/Disable the usage of a capability @var{capability} for migration.
+ETEXI
+
+    {
         .name       = "client_migrate_info",
         .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
         .params     = "protocol hostname port tls-port cert-subject",
@@ -1419,6 +1433,8 @@  show user network stack connection states
 show migration status
 @item info migrate_supported_capabilities
 show migrate supported capabilities
+@item info migrate_capabilities
+show current migration capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index b5c7afe..3448954 100644
--- a/hmp.c
+++ b/hmp.c
@@ -131,8 +131,21 @@  void hmp_info_mice(Monitor *mon)
 void hmp_info_migrate(Monitor *mon)
 {
     MigrationInfo *info;
+    MigrationCapabilityStatusList *caps, *cap;
 
     info = qmp_query_migrate(NULL);
+    caps = qmp_query_migrate_capabilities(NULL);
+
+    /* do not display parameters during setup */
+    if (info->has_status && caps) {
+        monitor_printf(mon, "capabilities: ");
+        for (cap = caps; cap; cap = cap->next) {
+            monitor_printf(mon, "%s: %s ",
+                           MigrationCapability_lookup[cap->value->capability],
+                           cap->value->state ? "on" : "off");
+        }
+        monitor_printf(mon, "\n");
+    }
 
     if (info->has_status) {
         monitor_printf(mon, "Migration status: %s\n", info->status);
@@ -159,6 +172,7 @@  void hmp_info_migrate(Monitor *mon)
     }
 
     qapi_free_MigrationInfo(info);
+    qapi_free_MigrationCapabilityStatusList(caps);
 }
 
 void hmp_info_migrate_supported_capabilities(Monitor *mon)
@@ -182,6 +196,25 @@  void hmp_info_migrate_supported_capabilities(Monitor *mon)
     qapi_free_MigrationCapabilityStatusList(caps_list);
 }
 
+void hmp_info_migrate_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps, *cap;
+
+    caps = qmp_query_migrate_capabilities(NULL);
+
+    if (caps) {
+        monitor_printf(mon, "capabilities: ");
+        for (cap = caps; cap; cap = cap->next) {
+            monitor_printf(mon, "%s: %s ",
+                           MigrationCapability_lookup[cap->value->capability],
+                           cap->value->state ? "on" : "off");
+        }
+        monitor_printf(mon, "\n");
+    }
+
+    qapi_free_MigrationCapabilityStatusList(caps);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
@@ -756,6 +789,38 @@  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
     qmp_migrate_set_speed(value, NULL);
 }
 
+void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
+{
+    const char *cap = qdict_get_str(qdict, "capability");
+    bool state = qdict_get_bool(qdict, "state");
+    Error *err = NULL;
+    MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
+    int i;
+
+    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
+            caps->value = g_malloc0(sizeof(*caps->value));
+            caps->value->capability = i;
+            caps->value->state = state;
+            caps->next = NULL;
+            qmp_migrate_set_capabilities(caps, &err);
+            break;
+        }
+    }
+
+    if (i == MIGRATION_CAPABILITY_MAX) {
+        error_set(&err, QERR_INVALID_PARAMETER, cap);
+    }
+
+    qapi_free_MigrationCapabilityStatusList(caps);
+
+    if (err) {
+        monitor_printf(mon, "migrate_set_parameter: %s\n",
+                       error_get_pretty(err));
+        error_free(err);
+    }
+}
+
 void hmp_set_password(Monitor *mon, const QDict *qdict)
 {
     const char *protocol  = qdict_get_str(qdict, "protocol");
diff --git a/hmp.h b/hmp.h
index a6194c1..584bd3d 100644
--- a/hmp.h
+++ b/hmp.h
@@ -26,6 +26,7 @@  void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
 void hmp_info_migrate_supported_capabilities(Monitor *mon);
+void hmp_info_migrate_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
@@ -52,6 +53,7 @@  void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict);
 void hmp_set_password(Monitor *mon, const QDict *qdict);
 void hmp_expire_password(Monitor *mon, const QDict *qdict);
 void hmp_eject(Monitor *mon, const QDict *qdict);
diff --git a/migration.c b/migration.c
index fc40f1f..d5b31ec 100644
--- a/migration.c
+++ b/migration.c
@@ -113,6 +113,30 @@  uint64_t migrate_max_downtime(void)
     return max_downtime;
 }
 
+MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *head = NULL;
+    MigrationCapabilityStatusList *caps;
+    MigrationState *s = migrate_get_current();
+    int i;
+
+    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+        if (head == NULL) {
+            head = g_malloc0(sizeof(*caps));
+            caps = head;
+        } else {
+            caps->next = g_malloc0(sizeof(*caps));
+            caps = caps->next;
+        }
+        caps->value =
+            g_malloc(sizeof(*caps->value));
+        caps->value->capability = i;
+        caps->value->state = s->enabled_capabilities[i];
+    }
+
+    return head;
+}
+
 MigrationInfo *qmp_query_migrate(Error **errp)
 {
     MigrationInfo *info = g_malloc0(sizeof(*info));
@@ -179,6 +203,22 @@  qmp_query_migrate_supported_capabilities(Error **errp)
     return caps_list;
 }
 
+void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
+                                  Error **errp)
+{
+    MigrationState *s = migrate_get_current();
+    MigrationCapabilityStatusList *cap;
+
+    if (s->state == MIG_STATE_ACTIVE) {
+        error_set(errp, QERR_MIGRATION_ACTIVE);
+        return;
+    }
+
+    for (cap = params; cap; cap = cap->next) {
+        s->enabled_capabilities[cap->value->capability] = cap->value->state;
+    }
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
@@ -388,10 +428,16 @@  static MigrationState *migrate_init(const MigrationParams *params)
 {
     MigrationState *s = migrate_get_current();
     int64_t bandwidth_limit = s->bandwidth_limit;
+    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
+
+    memcpy(enabled_capabilities, s->enabled_capabilities,
+           sizeof(enabled_capabilities));
 
     memset(s, 0, sizeof(*s));
     s->bandwidth_limit = bandwidth_limit;
     s->params = *params;
+    memcpy(s->enabled_capabilities, enabled_capabilities,
+           sizeof(enabled_capabilities));
 
     s->bandwidth_limit = bandwidth_limit;
     s->state = MIG_STATE_SETUP;
diff --git a/migration.h b/migration.h
index 57572a6..713aae0 100644
--- a/migration.h
+++ b/migration.h
@@ -19,6 +19,7 @@ 
 #include "notify.h"
 #include "error.h"
 #include "vmstate.h"
+#include "qapi-types.h"
 
 struct MigrationParams {
     bool blk;
@@ -39,6 +40,7 @@  struct MigrationState
     void *opaque;
     MigrationParams params;
     int64_t total_time;
+    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
 };
 
 void process_incoming_migration(QEMUFile *f);
diff --git a/monitor.c b/monitor.c
index d09cf4e..3c005d5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2669,6 +2669,13 @@  static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate_supported_capabilities,
     },
     {
+        .name       = "migrate_capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show current migration capabilities",
+        .mhandler.info = hmp_info_migrate_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index 8050069..b5d003c 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -345,6 +345,27 @@ 
 { 'command': 'query-migrate-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
 
 ##
+# @migrate-set-capabilities
+#
+# Enable/Disable the following migration capabilities (like xbzrle)
+#
+# Since: 1.2
+##
+{ 'command': 'migrate-set-capabilities',
+  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
+
+##
+# @query-migrate-capabilities
+#
+# Returns information about the current migration capabilities status
+#
+# Returns: @MigrationCapabilitiesStatus
+#
+# Since: 1.2
+##
+{ 'command': 'query-migrate-capabilities', 'returns':   ['MigrationCapabilityStatus']}
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index d2f68ab..78300fb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2166,6 +2166,55 @@  EQMP
     },
 
 SQMP
+migrate-set-capabilities
+-------
+
+Enable/Disable migration capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "migrate-set-capabilities" , "arguments":
+     { "capabilities": [ { "capability": "xbzrle", "state": true } ] } }
+
+EQMP
+
+    {
+        .name       = "migrate-set-capabilities",
+        .args_type  = "capabilities:O",
+        .params     = "capability:s,state:b",
+	.mhandler.cmd_new = qmp_marshal_input_migrate_set_capabilities,
+    },
+SQMP
+query-migrate-capabilities
+-------
+
+Query current migration capabilities
+
+- "capabilities": migration capabilities state
+         - "xbzrle" : XBZRLE state (json-bool)
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migrate-capabilities" }
+<- { "return": {
+        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
+     }
+   }
+EQMP
+
+    {
+        .name       = "query-migrate-capabilities",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_migrate_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------