Re: [libvirt] [PATCH 1/4] QEMU guest agent support

2012-01-23 Thread Daniel P. Berrange
On Thu, Jan 19, 2012 at 03:18:00PM -0700, Eric Blake wrote:
 On 01/17/2012 04:44 AM, Michal Privoznik wrote:
  There is now a standard QEMU guest agent that can be installed
  and given a virtio serial channel
  
  channel type='unix'
source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/
 
 Do we really want to be documenting a path in the libvirt-controlled
 hierarchy?

This is an artifact of the way we are doing the guest agent
support today.

If you look at the SPICE guest agent, there is a special channel
type 'spicevmc' that is used, and QEMU deals with that internally.

In the future, QEMU will deal with its own guest agent internally
and thus we'll have a new channel type kinda like 'spicevmc' which
does not expose any paths.

For now though, we're using the externally managed agent for
which we do want to expose the path IMHO.

Daniel
-- 
|: http://berrange.com  -o-http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org  -o- http://virt-manager.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org   -o-   http://live.gnome.org/gtk-vnc :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 1/4] QEMU guest agent support

2012-01-23 Thread Daniel P. Berrange
On Fri, Jan 20, 2012 at 07:16:22PM +0100, Michal Privoznik wrote:
 On 19.01.2012 23:18, Eric Blake wrote:
  On 01/17/2012 04:44 AM, Michal Privoznik wrote:
  There is now a standard QEMU guest agent that can be installed
  and given a virtio serial channel
 
  channel type='unix'
source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/

[snip]

 I am not sure we want this. Although I am not fully convinced by the
 opposite. Thing is, I don't want to enable something by default because
 users might have not noticed and things may break for them.
 On the other hand, users will definitely benefit from this feature so
 making it as easy as possible to enable is the right step.
 My initial thought is to have simple one line element:
 guest_agent name=org.qemu.guest_agent.0/
 
 with name defaulting to org.qemu.guest_agent.0 so simply inserting
 bare guest_agent/ will turn everything on?

No, we don't want to go about inventing new syntax for that - the
very purpose of any channel element is to support a guest agent,
so it is pointless creating another guest_agent element.

Daniel
-- 
|: http://berrange.com  -o-http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org  -o- http://virt-manager.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org   -o-   http://live.gnome.org/gtk-vnc :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 1/4] QEMU guest agent support

2012-01-20 Thread Michal Privoznik
On 19.01.2012 23:18, Eric Blake wrote:
 On 01/17/2012 04:44 AM, Michal Privoznik wrote:
 There is now a standard QEMU guest agent that can be installed
 and given a virtio serial channel

 channel type='unix'
   source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/
 
 Do we really want to be documenting a path in the libvirt-controlled
 hierarchy?
 
 Or is this something that we should be automatically creating on the
 user's behalf if it is apparent that qemu supports it, rather than
 requiring the user to modify their XML to add it?  At which point, it
 would _not_ be part of 'virsh dumpxml' output, but would only be visible
 in the /var/run/libvirt/qemu/dom.xml runtime state (similar to  how
 domstatus/monitor is the chardev element automatically created for
 the monitor)?
 
   target type='virtio' name='org.qemu.guest_agent.0'/
 /channel


 
 +++ b/src/qemu/qemu_process.c
 @@ -107,6 +107,164 @@ qemuProcessRemoveDomainStatus(struct qemud_driver 
 *driver,
  extern struct qemud_driver *qemu_driver;
  
  /*
 + * This is a callback registered with a qemuAgentPtr instance,
 + * and to be invoked when the agent console hits an end of file
 + * condition, or error, thus indicating VM shutdown should be
 + * performed
 
 Does agent shutdown really imply VM shutdown?  I hope not - that should
 be reserved for just monitor EOF.

Yes. You won't receive EOF if you close guest agent. But you'll get EOF
when qemu closes the socket. Even during reboots this socket remains
opened. So it is like monitor.
 
 +static virDomainChrSourceDefPtr
 +qemuFindAgentConfig(virDomainDefPtr def)
 +{
 +virDomainChrSourceDefPtr config = NULL;
 +int i;
 +
 +for (i = 0 ; i  def-nchannels ; i++) {
 +virDomainChrDefPtr channel = def-channels[i];
 +
 +if (channel-targetType != 
 VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
 +continue;
 +
 +if (STREQ(channel-target.name, org.qemu.guest_agent.0)) {
 +config = channel-source;
 +break;
 +}
 +}
 
 This implementation requires users to add the agent in their XML; is
 there any way we can automate the use of an agent without doing this?

I am not sure we want this. Although I am not fully convinced by the
opposite. Thing is, I don't want to enable something by default because
users might have not noticed and things may break for them.
On the other hand, users will definitely benefit from this feature so
making it as easy as possible to enable is the right step.
My initial thought is to have simple one line element:
guest_agent name=org.qemu.guest_agent.0/

with name defaulting to org.qemu.guest_agent.0 so simply inserting
bare guest_agent/ will turn everything on?

 Then again, it's not just that qemu has to be new enough to have agent
 support, but it's also that the guest has to have an agent installed.
 Maybe we should consider (as a followup, not for this patch) an XML
 shorthand that lets the user request use of an agent without having to
 specify full details (that is, without having to choose a patch for the
 socket, and without having to know the name org.qemu.guest_agent.0 for
 the protocol of a channel).
 
 Overall, I'm looking forward to using the agent (I want to support a new
 flag to snapshot creation that uses the agent's ability to request file
 system queiscing from the guest).
 

Thanks for review and watch out for v2 :) (as soon as we settle down on
XML part)

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 1/4] QEMU guest agent support

2012-01-19 Thread Eric Blake
On 01/17/2012 04:44 AM, Michal Privoznik wrote:
 There is now a standard QEMU guest agent that can be installed
 and given a virtio serial channel
 
 channel type='unix'
   source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/

Do we really want to be documenting a path in the libvirt-controlled
hierarchy?

Or is this something that we should be automatically creating on the
user's behalf if it is apparent that qemu supports it, rather than
requiring the user to modify their XML to add it?  At which point, it
would _not_ be part of 'virsh dumpxml' output, but would only be visible
in the /var/run/libvirt/qemu/dom.xml runtime state (similar to  how
domstatus/monitor is the chardev element automatically created for
the monitor)?

   target type='virtio' name='org.qemu.guest_agent.0'/
 /channel
 
 The protocol that runs over the guest agent is JSON based and
 very similar to the JSON monitor. We can't use exactly the same
 code because there are some odd differences in the way messages
 and errors are structured. The qemu_agent.c file is based on
 a combination and simplification of qemu_monitor.c and
 qemu_monitor_json.c
 
 * src/qemu/qemu_agent.c, src/qemu/qemu_agent.h: Support for
   talking to the agent for shutdown
 * src/qemu/qemu_domain.c, src/qemu/qemu_domain.h: Add thread
   helpers for talking to the agent
 * src/qemu/qemu_process.c: Connect to agent whenever starting
   a guest
 * src/qemu/qemu_monitor_json.c: Make variable static

 +struct _qemuAgentMessage {
 +char *txBuffer;
 +int txOffset;
 +int txLength;
 +
 +/* Used by the text monitor reply / error */
 +char *rxBuffer;
 +int rxLength;

This comment is misleading, since we are a JSON monitor and not a text
monitor.

 +/* Used by the JSON monitor to hold reply / error */
 +void *rxObject;
 +
 +/* True if rxBuffer / rxObject are ready, or a
 + * fatal error occurred on the monitor channel
 + */
 +bool finished;
 +};
 +

 +
 +#if DEBUG_RAW_IO
 +# include c-ctype.h
 +static char * qemuAgentEscapeNonPrintable(const char *text)

Formatting - I'd do this in two lines:

static char *
qemuAgentEscapeNonPrintable(const char *text)

 +{
 +int i;
 +virBuffer buf = VIR_BUFFER_INITIALIZER;
 +for (i = 0 ; text[i] != '\0' ; i++) {
 +if (c_isprint(text[i]) ||
 +text[i] == '\n' ||
 +(text[i] == '\r'  text[i+1] == '\n'))
 +virBufferAsprintf(buf,%c, text[i]);
 +else
 +virBufferAsprintf(buf, 0x%02x, text[i]);

That gives ambiguous output, and isn't very efficient.  I'd do it more like:

if (text[i] == '\\')
virBufferAddLit(buf, );
else if (c_isprint(text[i]) || text[i] == '\n' ||
 (text[i] == '\r'  text[i+1] == '\n'))
virBufferAddChar(buf, text[i]);
else
virBufferAsprintf(buf, \\x%02x, text[i]);

 +static int
 +qemuAgentOpenUnix(const char *monitor, pid_t cpid, bool *inProgress)
 +{
 +struct sockaddr_un addr;
 +int monfd;
 +int timeout = 3; /* In seconds */
 +int ret, i = 0;
 +
 +*inProgress = false;
 +
 +if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0))  0) {
 +virReportSystemError(errno,
 + %s, _(failed to create socket));
 +return -1;
 +}
 +
 +if (virSetNonBlock(monfd)  0) {
 +qemuReportError(VIR_ERR_INTERNAL_ERROR,
 +%s, _(Unable to put monitor into non-blocking 
 mode));
 +goto error;
 +}
 +
 +if (virSetCloseExec(monfd)  0) {
 +qemuReportError(VIR_ERR_INTERNAL_ERROR,
 +%s, _(Unable to set monitor close-on-exec flag));
 +goto error;
 +}

You know, if I ever got around to fixing gnulib to guarantee things for
older platforms, we could use socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC
| SOCK_NONBLOCK, 0) and shave off a few syscalls.  But for now, your
code is the best we can do.

 +static int
 +qemuAgentOpenPty(const char *monitor)
 +{
 +int monfd;
 +
 +if ((monfd = open(monitor, O_RDWR))  0) {
 +qemuReportError(VIR_ERR_INTERNAL_ERROR,
 +_(Unable to open monitor path %s), monitor);
 +return -1;
 +}
 +
 +if (virSetNonBlock(monfd)  0) {
 +qemuReportError(VIR_ERR_INTERNAL_ERROR,
 +%s, _(Unable to put monitor into non-blocking 
 mode));
 +goto error;
 +}

Why not open(monitor, O_RDWR | O_NONBLOCK), and shave off a syscall here?

 +
 +if (virSetCloseExec(monfd)  0) {
 +qemuReportError(VIR_ERR_INTERNAL_ERROR,
 +%s, _(Unable to set monitor close-on-exec flag));
 +goto error;
 +}

Alas, I also need to find time to make gnulib guarantee open(O_CLOEXEC).

 +static int qemuAgentIOProcessData(qemuAgentPtr mon,
 +  const char *data,
 +  size_t len,
 +  qemuAgentMessagePtr msg)
 +{
 +int used = 0;
 

Re: [libvirt] [PATCH 1/4] QEMU guest agent support

2011-10-05 Thread Eric Blake

On 10/05/2011 11:31 AM, Daniel P. Berrange wrote:

From: Daniel P. Berrangeberra...@redhat.com

There is now a standard QEMU guest agent that can be installed
and given a virtio serial channel

 channel type='unix'
   source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/
   target type='virtio' name='org.qemu.guest_agent.0'/
 /channel


And the next step would be to have virt-manager/virt-install 
automatically set this up when creating new domains.




The protocol that runs over the guest agent is JSON based and
very similar to the JSON monitor. We can't use exaclty the same


s/exaclty/exactly/


code because there are some odd differences in the way messages
and errors are strucutured. The qemu_agent.c file is based on


s/strucutured/structured/


a combination and simplification of qemu_monitor.c and
qemu_monitor_json.c

* src/qemu/qemu_agent.c, src/qemu/qemu_agent.h: Support for
   talking to the agent for shutdown
* src/qemu/qemu_domain.c, src/qemu/qemu_domain.h: Add thread
   helpers for talking to the agent
* src/qemu/qemu_process.c: Connect to agent whenever starting
   a guest
* src/qemu/qemu_monitor_json.c: Make variable static
---
  src/Makefile.am  |1 +
  src/qemu/qemu_agent.c| 1135 ++
  src/qemu/qemu_agent.h|   69 +++
  src/qemu/qemu_domain.c   |   97 
  src/qemu/qemu_domain.h   |   22 +
  src/qemu/qemu_monitor_json.c |2 +-
  src/qemu/qemu_process.c  |  187 +++
  7 files changed, 1512 insertions(+), 1 deletions(-)
  create mode 100644 src/qemu/qemu_agent.c
  create mode 100644 src/qemu/qemu_agent.h


We'll see how far I get in this review.  At any rate, this patch should 
be independently back-portable to Fedora 16 without requiring a rebase, 
although the same cannot be said of patches 2-4.



+
+static struct {
+const char *type;
+void (*handler)(qemuAgentPtr mon, virJSONValuePtr data);
+} eventHandlers[] = {
+};


What good is a 0-element initializer?  Should we nuke this struct until 
we actually have an event that we need to handle?



+
+static void qemuAgentFree(qemuAgentPtr mon)
+{
+VIR_DEBUG(mon=%p, mon);
+if (mon-cb  mon-cb-destroy)
+(mon-cb-destroy)(mon, mon-vm);
+if (virCondDestroy(mon-notify)  0)
+{}


I'd write this as:

ignore_value(virCondDestroy(mon-notify));

I know it was just copy-and-paste from old code that predated our use of 
ignore_value.



+static int
+qemuAgentOpenUnix(const char *monitor, pid_t cpid, bool *inProgress)
+{
+struct sockaddr_un addr;
+int monfd;
+int timeout = 3; /* In seconds */
+int ret, i = 0;
+
+*inProgress = false;
+
+if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0))  0) {
+virReportSystemError(errno,
+ %s, _(failed to create socket));
+return -1;
+}
+
+if (virSetNonBlock(monfd)  0) {


Someday, I'll get gnulib to support SOCK_NONBLOCK, so we can do this in 
fewer kernel calls with newer kernels...



+
+static int
+qemuAgentIOProcessEvent(qemuAgentPtr mon,
+virJSONValuePtr obj)
+{
+const char *type;
+int i;
+VIR_DEBUG(mon=%p obj=%p, mon, obj);
+
+type = virJSONValueObjectGetString(obj, event);
+if (!type) {
+VIR_WARN(missing event type in message);
+errno = EINVAL;
+return -1;
+}
+
+for (i = 0 ; i  ARRAY_CARDINALITY(eventHandlers) ; i++) {


I guess you really are using a 0-element array.  But does that compile 
correctly on all C99 compilers, or should we also be commenting out this 
function as long as we lack agent events?



+
+static int qemuAgentIOProcessData(qemuAgentPtr mon,
+  const char *data,
+  size_t len,
+  qemuAgentMessagePtr msg)
+{
+int used = 0;
+#if DEBUG_IO
+# if DEBUG_RAW_IO
+char *str1 = qemuAgentEscapeNonPrintable(data);
+VIR_ERROR(_([%s]), str1);


Doesn't this trip up 'make syntax-check', since VIR_ERROR shouldn't need 
to translate its string?



+/* This method processes data that has been received
+ * from the monitor. Looking for async events and
+ * replies/errors.
+ */
+static int
+qemuAgentIOProcess(qemuAgentPtr mon)
+{
+int len;
+qemuAgentMessagePtr msg = NULL;
+
+/* See if there's a message  whether its ready for its reply
+ * ie whether its completed writing all its data */


Copy-and-paste, but the grammar here is awful.  How about:

See if there's a message ready for reply; that is, one that has 
completed writing all its data.



+if (mon-msg  mon-msg-txOffset == mon-msg-txLength)
+msg = mon-msg;
+
+#if DEBUG_IO
+# if DEBUG_RAW_IO
+char *str1 = qemuAgentEscapeNonPrintable(msg ? msg-txBuffer : );
+char *str2 = qemuAgentEscapeNonPrintable(mon-buffer);
+VIR_ERROR(_(Process %d %p %p %s]]][[[%s]]]), (int)mon-bufferOffset, 
mon-msg, msg, str1, str2);


Unbalanced: