[libvirt] [PATCH 11/14] Support for JSON mode monitor

Daniel P. Berrange berrange at redhat.com
Thu Dec 3 15:28:02 UTC 2009


On Thu, Dec 03, 2009 at 04:05:54PM +0100, Daniel Veillard wrote:
> On Thu, Nov 26, 2009 at 06:27:29PM +0000, Daniel P. Berrange wrote:
> > Initial support for the new QEMU monitor protocol  using JSON
> > as the data encoding format instead of plain text
> [...]
> > --- a/src/Makefile.am
> > +++ b/src/Makefile.am
> > @@ -188,6 +188,8 @@ QEMU_DRIVER_SOURCES =						\
> >  		qemu/qemu_monitor.c qemu/qemu_monitor.h		\
> >  		qemu/qemu_monitor_text.c			\
> >  		qemu/qemu_monitor_text.h			\
> > +		qemu/qemu_monitor_json.c			\
> > +		qemu/qemu_monitor_json.h			\
> >  		qemu/qemu_driver.c qemu/qemu_driver.h        	\
> >  		qemu/qemu_bridge_filter.c 			\
> 
>   Hum could you take the opportunity to cleanup the tab/space mix
> in the 2 following lines, above ?
> 
> [...]
> > @@ -283,9 +285,14 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
> >          msg = mon->msg;
> >  
> >      VIR_DEBUG("Process %d", (int)mon->bufferOffset);
> > -    len = qemuMonitorTextIOProcess(mon,
> > -                                   mon->buffer, mon->bufferOffset,
> > -                                   msg);
> > +    if (mon->json)
> > +        len = qemuMonitorJSONIOProcess(mon,
> > +                                       mon->buffer, mon->bufferOffset,
> > +                                       msg);
> > +    else
> > +        len = qemuMonitorTextIOProcess(mon,
> > +                                       mon->buffer, mon->bufferOffset,
> > +                                       msg);
> 
>   I have just one doubt here, assuming we have a json handle, is the
> text monitor still available. In which case should we try to fallback
> assuming the json interface get into troubles ? I assume if one fail
> then the other should fail too but ...

No, QEMU works in an either/or  mode - you can't have both active. 

> > +#define LINE_ENDING "\r\n"
> > +
> > +static int
> > +qemuMonitorJSONIOProcessLine(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> > +                             const char *line,
> > +                             qemuMonitorMessagePtr msg)
> > +{
> > +    virJSONValuePtr obj = NULL;
> > +    int ret = -1;
> > +
> > +    VIR_DEBUG("Line [%s]", line);
> > +
> > +    if (!(obj = virJSONValueFromString(line))) {
> > +        VIR_DEBUG0("Parsing JSON string failed");
> > +        errno = EINVAL;
> > +        goto cleanup;
> > +    }
> > +
> > +    if (obj->type != VIR_JSON_TYPE_OBJECT) {
> > +        VIR_DEBUG0("Parsed JSON string isn't an object");
> > +        errno = EINVAL;
> > +    }
> > +
> > +    if (virJSONValueObjectHasKey(obj, "QMP") == 1) {
> > +        VIR_DEBUG0("Got QMP capabilities data");
> > +        ret = 0;
> > +        goto cleanup;
> > +    }
> > +
> > +    if (virJSONValueObjectHasKey(obj, "event") == 1) {
> > +        VIR_DEBUG0("Got an event");
> > +        ret = 0;
> > +        goto cleanup;
> > +    }
> > +
> > +    if (msg) {
> > +        msg->rxBuffer = strdup(line);
> > +        msg->rxLength = strlen(line);
> > +        msg->finished = 1;
> > +    } else {
> > +        VIR_DEBUG("Ignoring unexpected JSON message [%s]", line);
> > +    }
> > +
> > +    ret = 0;
> > +
> > +cleanup:
> > +    virJSONValueFree(obj);
> > +    return ret;
> > +}
> 
>   I must be missing something in that routine, we parse the json blob,
> get an object, check some of the object content and discard it, saving
> the raw text .... seems to me we dropped the actual parsed content
> instead of handling it, no ?

Yes this is a little bit of a wierd scenario, mostly an artifact of
the way we have code sharing between the text & json modes. The shared
I/O handling code simply works on char * buffers, and so we can't 
easily pass back the parsed JSON object at this point. So the object
here is only used for detecting events - it is reparsed later on in
the place which handles method replies/errors. A little inefficient
perhaps, but these messages are very small so its not really too bad

> > +    while ((key = va_arg(args, char *)) != NULL) {
> > +        int ret;
> > +        char type;
> > +
> > +        if (strlen(key) < 3) {
> > +            qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> > +                             _("argument key '%s' is too short, missing type prefix"),
> > +                             key);
> > +            goto error;
> > +        }
> > +
> > +        /* Keys look like   s:name  the first letter is a type code */
> > +        type = key[0];
> > +        key += 2;
> 
>   Hum, we add a type info on top using prefixing ... weird but why not ...

I originally had 3 values per param in the callers, eg

   qemuMonitorJSONMakeCommand("eject",
                              "device, VIR_JSON_VALUE_STRING, "hda",
                              NULL)

but I thought it was getting far too verbose, so I switched to this
simple type format character

   qemuMonitorJSONMakeCommand("eject",
       	       	       	      "s:device, "hda",
                              NULL)


Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list