Patchwork qmp: report TRAY_STATE_CHANGED events

login
register
mail settings
Submitter Paolo Bonzini
Date Oct. 25, 2011, 4:26 p.m.
Message ID <1319560018-25788-1-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/121743/
State New
Headers show

Comments

Paolo Bonzini - Oct. 25, 2011, 4:26 p.m.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 QMP/qmp-events.txt |   20 ++++++++++++++++++++
 block.c            |    9 +++++++++
 monitor.c          |    3 +++
 monitor.h          |    1 +
 4 files changed, 33 insertions(+), 0 deletions(-)
Luiz Capitulino - Oct. 25, 2011, 6:44 p.m.
On Tue, 25 Oct 2011 18:26:58 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  QMP/qmp-events.txt |   20 ++++++++++++++++++++
>  block.c            |    9 +++++++++
>  monitor.c          |    3 +++
>  monitor.h          |    1 +
>  4 files changed, 33 insertions(+), 0 deletions(-)
> 
> diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
> index 0ce5d4e..242c7a5 100644
> --- a/QMP/qmp-events.txt
> +++ b/QMP/qmp-events.txt
> @@ -264,3 +264,23 @@ Example:
>  
>  Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
>  followed respectively by the RESET, SHUTDOWN, or STOP events.
> +
> +
> +TRAY_STATE_CHANGED
> +------------------
> +
> +Emitted when the state of a CD-ROM tray changes.
> +
> +Data:
> +
> +- "device": device name (json-string)
> +- "state": state of the tray, one of the following (json-string)
> +   "open": tray is open
> +   "closed": tray is closed

Wouldn't be better to make this a bool?

CC'ing the block guys to get ACKs from them too.

> +
> +Example:
> +
> +{ "event": "TRAY_STATE_CHANGED",
> +    "data": { "device": "ide0-cd0",
> +              "state": "open" },
> +    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
> diff --git a/block.c b/block.c
> index 9873b57..7b0aa62 100644
> --- a/block.c
> +++ b/block.c
> @@ -2968,10 +2968,19 @@ int bdrv_media_changed(BlockDriverState *bs)
>  void bdrv_eject(BlockDriverState *bs, int eject_flag)
>  {
>      BlockDriver *drv = bs->drv;
> +    QObject *data;
>  
>      if (drv && drv->bdrv_eject) {
>          drv->bdrv_eject(bs, eject_flag);
>      }
> +
> +    if (*bs->device_name) {
> +        data = qobject_from_jsonf("{ 'device': %s, 'state': %s }",
> +                                  bs->device_name,
> +                                  eject_flag ? "open" : "closed");
> +        monitor_protocol_event(QEVENT_TRAY_STATE_CHANGED, data);
> +        qobject_decref(data);
> +    }
>  }
>  
>  /**
> diff --git a/monitor.c b/monitor.c
> index ffda0fe..516a789 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -482,6 +482,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
>          case QEVENT_SPICE_DISCONNECTED:
>              event_name = "SPICE_DISCONNECTED";
>              break;
> +        case QEVENT_TRAY_STATE_CHANGED:
> +            event_name = "TRAY_STATE_CHANGED";
> +            break;
>          default:
>              abort();
>              break;
> diff --git a/monitor.h b/monitor.h
> index 4f2d328..b8f4bf7 100644
> --- a/monitor.h
> +++ b/monitor.h
> @@ -35,6 +35,7 @@ typedef enum MonitorEvent {
>      QEVENT_SPICE_CONNECTED,
>      QEVENT_SPICE_INITIALIZED,
>      QEVENT_SPICE_DISCONNECTED,
> +    QEVENT_TRAY_STATE_CHANGED,
>      QEVENT_MAX,
>  } MonitorEvent;
>
Sheldon - Nov. 1, 2011, 5:03 a.m.
test-by: ShaoHe Feng<shaohef@linux.vnet.ibm.com>

It seems this patch can not work well.

there is my test process.

I startup a guest by the follow option:  -drive 
file=/home/fsh/image/OCDC-natty-Test-Drive-20110823_010339.iso,if=ide,index=1,media=cdrom

after the guest startups, then I right click mouse in the UI of the 
guest,  and select the Eject from the menu.
there comes an event in the qmp-monitor.
{"timestamp": {"seconds": 1320118137, "microseconds": 420150}, "event": 
"TRAY_STATE_CHANGED", "data": {"device": "ide0-cd1", "state": "open"}}

however, if I change the cdrom by this command:
{ "execute": "change","arguments": { "device": "ide0-cd1", "target": 
"/home/fsh/image/OCDC-natty-Test-Drive-20110823_010339.iso" } }
there is no any event.

and { "execute": "eject", "arguments": { "device": "ide0-cd1" } },
there is also no any event.

only I right click mouse in the UI of the guest,  qmp-monitor can 
receive an TRAY_STATE_CHANGED event.

, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> ---
>   QMP/qmp-events.txt |   20 ++++++++++++++++++++
>   block.c            |    9 +++++++++
>   monitor.c          |    3 +++
>   monitor.h          |    1 +
>   4 files changed, 33 insertions(+), 0 deletions(-)
>
> diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
> index 0ce5d4e..242c7a5 100644
> --- a/QMP/qmp-events.txt
> +++ b/QMP/qmp-events.txt
> @@ -264,3 +264,23 @@ Example:
>
>   Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
>   followed respectively by the RESET, SHUTDOWN, or STOP events.
> +
> +
> +TRAY_STATE_CHANGED
> +------------------
> +
> +Emitted when the state of a CD-ROM tray changes.
> +
> +Data:
> +
> +- "device": device name (json-string)
> +- "state": state of the tray, one of the following (json-string)
> +   "open": tray is open
> +   "closed": tray is closed
> +
> +Example:
> +
> +{ "event": "TRAY_STATE_CHANGED",
> +    "data": { "device": "ide0-cd0",
> +              "state": "open" },
> +    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
> diff --git a/block.c b/block.c
> index 9873b57..7b0aa62 100644
> --- a/block.c
> +++ b/block.c
> @@ -2968,10 +2968,19 @@ int bdrv_media_changed(BlockDriverState *bs)
>   void bdrv_eject(BlockDriverState *bs, int eject_flag)
>   {
>       BlockDriver *drv = bs->drv;
> +    QObject *data;
>
>       if (drv&&  drv->bdrv_eject) {
>           drv->bdrv_eject(bs, eject_flag);
>       }
> +
> +    if (*bs->device_name) {
> +        data = qobject_from_jsonf("{ 'device': %s, 'state': %s }",
> +                                  bs->device_name,
> +                                  eject_flag ? "open" : "closed");
> +        monitor_protocol_event(QEVENT_TRAY_STATE_CHANGED, data);
> +        qobject_decref(data);
> +    }
>   }
>
>   /**
> diff --git a/monitor.c b/monitor.c
> index ffda0fe..516a789 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -482,6 +482,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
>           case QEVENT_SPICE_DISCONNECTED:
>               event_name = "SPICE_DISCONNECTED";
>               break;
> +        case QEVENT_TRAY_STATE_CHANGED:
> +            event_name = "TRAY_STATE_CHANGED";
> +            break;
>           default:
>               abort();
>               break;
> diff --git a/monitor.h b/monitor.h
> index 4f2d328..b8f4bf7 100644
> --- a/monitor.h
> +++ b/monitor.h
> @@ -35,6 +35,7 @@ typedef enum MonitorEvent {
>       QEVENT_SPICE_CONNECTED,
>       QEVENT_SPICE_INITIALIZED,
>       QEVENT_SPICE_DISCONNECTED,
> +    QEVENT_TRAY_STATE_CHANGED,
>       QEVENT_MAX,
>   } MonitorEvent;
>
Paolo Bonzini - Nov. 4, 2011, 10:53 a.m.
On 11/01/2011 06:03 AM, ShaoHe Feng wrote:
> after the guest startups, then I right click mouse in the UI of the
> guest,  and select the Eject from the menu.
> there comes an event in the qmp-monitor.
> {"timestamp": {"seconds": 1320118137, "microseconds": 420150}, "event":
> "TRAY_STATE_CHANGED", "data": {"device": "ide0-cd1", "state": "open"}}
>
> however, if I change the cdrom by this command:
> { "execute": "change","arguments": { "device": "ide0-cd1", "target":
> "/home/fsh/image/OCDC-natty-Test-Drive-20110823_010339.iso" } }
> there is no any event.
> and { "execute": "eject", "arguments": { "device": "ide0-cd1" } },
> there is also no any event.

This was by design.  The idea was that management can do the following 
to change a CD when the guest keeps the medium locked and reacts to 
eject requests (like very recent Linux does):

Scenario 1: non-forced media change

      1. start looking at TRAY_STATE_CHANGED events
      2. execute "eject" command
      3. execute "query-block"
      4. if disk is still shown as closed, check for guest reactions:
         4.1. if no TRAY_STATE_CHANGED event has been reported since
              step 1, wait until a TRAY_STATE_CHANGED event has arrived
         4.2. if the TRAY_STATE_CHANGED event had state == closed, fail
      5. execute "change" command

Scenario 2: forced media change

      1. execute "eject -f" command (with the posted patches that
         always unlock the tray upon "eject -f")
      2. execute "change" command
      3. if it fails, restart

Paolo
Luiz Capitulino - Nov. 4, 2011, 5:25 p.m.
On Fri, 04 Nov 2011 11:53:53 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 11/01/2011 06:03 AM, ShaoHe Feng wrote:
> > after the guest startups, then I right click mouse in the UI of the
> > guest,  and select the Eject from the menu.
> > there comes an event in the qmp-monitor.
> > {"timestamp": {"seconds": 1320118137, "microseconds": 420150}, "event":
> > "TRAY_STATE_CHANGED", "data": {"device": "ide0-cd1", "state": "open"}}
> >
> > however, if I change the cdrom by this command:
> > { "execute": "change","arguments": { "device": "ide0-cd1", "target":
> > "/home/fsh/image/OCDC-natty-Test-Drive-20110823_010339.iso" } }
> > there is no any event.
> > and { "execute": "eject", "arguments": { "device": "ide0-cd1" } },
> > there is also no any event.
> 
> This was by design.  The idea was that management can do the following 
> to change a CD when the guest keeps the medium locked and reacts to 
> eject requests (like very recent Linux does):

Just a note: this didn't make 1.0... I replied to it but didn't get
feedback:

  http://lists.gnu.org/archive/html/qemu-devel/2011-10/msg03096.html

> 
> Scenario 1: non-forced media change
> 
>       1. start looking at TRAY_STATE_CHANGED events
>       2. execute "eject" command
>       3. execute "query-block"
>       4. if disk is still shown as closed, check for guest reactions:
>          4.1. if no TRAY_STATE_CHANGED event has been reported since
>               step 1, wait until a TRAY_STATE_CHANGED event has arrived
>          4.2. if the TRAY_STATE_CHANGED event had state == closed, fail
>       5. execute "change" command
> 
> Scenario 2: forced media change
> 
>       1. execute "eject -f" command (with the posted patches that
>          always unlock the tray upon "eject -f")
>       2. execute "change" command
>       3. if it fails, restart
> 
> Paolo
>

Patch

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index 0ce5d4e..242c7a5 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -264,3 +264,23 @@  Example:
 
 Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
 followed respectively by the RESET, SHUTDOWN, or STOP events.
+
+
+TRAY_STATE_CHANGED
+------------------
+
+Emitted when the state of a CD-ROM tray changes.
+
+Data:
+
+- "device": device name (json-string)
+- "state": state of the tray, one of the following (json-string)
+   "open": tray is open
+   "closed": tray is closed
+
+Example:
+
+{ "event": "TRAY_STATE_CHANGED",
+    "data": { "device": "ide0-cd0",
+              "state": "open" },
+    "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
diff --git a/block.c b/block.c
index 9873b57..7b0aa62 100644
--- a/block.c
+++ b/block.c
@@ -2968,10 +2968,19 @@  int bdrv_media_changed(BlockDriverState *bs)
 void bdrv_eject(BlockDriverState *bs, int eject_flag)
 {
     BlockDriver *drv = bs->drv;
+    QObject *data;
 
     if (drv && drv->bdrv_eject) {
         drv->bdrv_eject(bs, eject_flag);
     }
+
+    if (*bs->device_name) {
+        data = qobject_from_jsonf("{ 'device': %s, 'state': %s }",
+                                  bs->device_name,
+                                  eject_flag ? "open" : "closed");
+        monitor_protocol_event(QEVENT_TRAY_STATE_CHANGED, data);
+        qobject_decref(data);
+    }
 }
 
 /**
diff --git a/monitor.c b/monitor.c
index ffda0fe..516a789 100644
--- a/monitor.c
+++ b/monitor.c
@@ -482,6 +482,9 @@  void monitor_protocol_event(MonitorEvent event, QObject *data)
         case QEVENT_SPICE_DISCONNECTED:
             event_name = "SPICE_DISCONNECTED";
             break;
+        case QEVENT_TRAY_STATE_CHANGED:
+            event_name = "TRAY_STATE_CHANGED";
+            break;
         default:
             abort();
             break;
diff --git a/monitor.h b/monitor.h
index 4f2d328..b8f4bf7 100644
--- a/monitor.h
+++ b/monitor.h
@@ -35,6 +35,7 @@  typedef enum MonitorEvent {
     QEVENT_SPICE_CONNECTED,
     QEVENT_SPICE_INITIALIZED,
     QEVENT_SPICE_DISCONNECTED,
+    QEVENT_TRAY_STATE_CHANGED,
     QEVENT_MAX,
 } MonitorEvent;