Since we are adding a new "per-hypervisor" protocol, we
make it so that the qemu remote protocol uses a new
PROTOCOL and PROGRAM number. This allows us to easily
distinguish it from the normal REMOTE protocol.
This necessitates changing the proc in remote_message_header
from a "remote_procedure" to an "unsigned", which should
be the same size (and thus preserve the on-wire protocol).
Changes since v1:
- Fixed up a couple of script problems in remote_generate_stubs.pl
- Switch an int flag to a bool in dispatch.c
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
cfg.mk | 2 +-
daemon/Makefile.am | 32 +++++++++---
daemon/dispatch.c | 45 +++++++++++-----
daemon/libvirtd.h | 1 +
daemon/qemu_dispatch_args.h | 5 ++
daemon/qemu_dispatch_prototypes.h | 12 ++++
daemon/qemu_dispatch_ret.h | 5 ++
daemon/qemu_dispatch_table.h | 14 +++++
daemon/remote.c | 45 ++++++++++++++++
daemon/remote.h | 8 +++
daemon/remote_generate_stubs.pl | 62 ++++++++++++++--------
src/Makefile.am | 37 ++++++++++++-
src/remote/qemu_protocol.c | 41 ++++++++++++++
src/remote/qemu_protocol.h | 57 ++++++++++++++++++++
src/remote/qemu_protocol.x | 46 ++++++++++++++++
src/remote/remote_driver.c | 105 +++++++++++++++++++++++++++----------
src/remote/remote_protocol.c | 50 +++++++++++++++++-
src/remote/remote_protocol.h | 2 +-
src/remote/remote_protocol.x | 2 +-
19 files changed, 494 insertions(+), 77 deletions(-)
create mode 100644 daemon/qemu_dispatch_args.h
create mode 100644 daemon/qemu_dispatch_prototypes.h
create mode 100644 daemon/qemu_dispatch_ret.h
create mode 100644 daemon/qemu_dispatch_table.h
create mode 100644 src/remote/qemu_protocol.c
create mode 100644 src/remote/qemu_protocol.h
create mode 100644 src/remote/qemu_protocol.x
diff --git a/cfg.mk b/cfg.mk
index 96d6953..e9ea68c 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -399,7 +399,7 @@ sc_prohibit_trailing_blank_lines:
test $$found = 0
# Regex for grep -E that exempts generated files from style rules.
-preprocessor_exempt = (remote_(driver|protocol)\.h)$$
+preprocessor_exempt = ((qemu|remote)_(driver|protocol)\.h)$$
# Enforce recommended preprocessor indentation style.
sc_preprocessor_indentation:
@if cppi --version >/dev/null 2>&1; then \
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index a82e9a9..089f1aa 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -10,7 +10,8 @@ DAEMON_SOURCES = \
remote_dispatch_table.h \
remote_dispatch_args.h \
remote_dispatch_ret.h \
- ../src/remote/remote_protocol.c
+ ../src/remote/remote_protocol.c \
+ ../src/remote/qemu_protocol.c
AVAHI_SOURCES = \
mdns.c mdns.h
@@ -76,7 +77,7 @@ libvirtd_LDADD = \
$(SASL_LIBS) \
$(POLKIT_LIBS)
-libvirtd_LDADD += ../src/libvirt_util.la
+libvirtd_LDADD += ../src/libvirt_util.la ../src/libvirt-qemu.la
if WITH_DRIVER_MODULES
libvirtd_LDADD += ../src/libvirt_driver.la
@@ -167,21 +168,38 @@ endif
remote.c: remote_dispatch_prototypes.h \
remote_dispatch_table.h \
remote_dispatch_args.h \
- remote_dispatch_ret.h
+ remote_dispatch_ret.h \
+ qemu_dispatch_prototypes.h \
+ qemu_dispatch_table.h \
+ qemu_dispatch_args.h \
+ qemu_dispatch_ret.h
REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x
+QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x
remote_dispatch_prototypes.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
- $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -p $(REMOTE_PROTOCOL) > $@
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -p remote $(REMOTE_PROTOCOL)
> $@
remote_dispatch_table.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
- $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -t $(REMOTE_PROTOCOL) > $@
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -t remote $(REMOTE_PROTOCOL)
> $@
remote_dispatch_args.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
- $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -a $(REMOTE_PROTOCOL) > $@
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -a remote $(REMOTE_PROTOCOL)
> $@
remote_dispatch_ret.h: $(srcdir)/remote_generate_stubs.pl $(REMOTE_PROTOCOL)
- $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -r $(REMOTE_PROTOCOL) > $@
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -c -r remote $(REMOTE_PROTOCOL)
> $@
+
+qemu_dispatch_prototypes.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL)
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -p qemu $(QEMU_PROTOCOL) > $@
+
+qemu_dispatch_table.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL)
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -t qemu $(QEMU_PROTOCOL) > $@
+
+qemu_dispatch_args.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL)
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -a qemu $(QEMU_PROTOCOL) > $@
+
+qemu_dispatch_ret.h: $(srcdir)/remote_generate_stubs.pl $(QEMU_PROTOCOL)
+ $(AM_V_GEN)perl -w $(srcdir)/remote_generate_stubs.pl -r qemu $(QEMU_PROTOCOL) > $@
LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \
libvirtd.uml.logrotate
diff --git a/daemon/dispatch.c b/daemon/dispatch.c
index 8f55eaa..2b21111 100644
--- a/daemon/dispatch.c
+++ b/daemon/dispatch.c
@@ -23,6 +23,8 @@
#include <config.h>
+#include <stdbool.h>
+
#include "dispatch.h"
#include "remote.h"
@@ -336,10 +338,11 @@ cleanup:
}
-int
+static int
remoteDispatchClientCall (struct qemud_server *server,
struct qemud_client *client,
- struct qemud_client_message *msg);
+ struct qemud_client_message *msg,
+ bool qemu_protocol);
/*
@@ -356,12 +359,13 @@ remoteDispatchClientCall (struct qemud_server *server,
* Returns 0 if the message was dispatched, -1 upon fatal error
*/
int
-remoteDispatchClientRequest (struct qemud_server *server,
- struct qemud_client *client,
- struct qemud_client_message *msg)
+remoteDispatchClientRequest(struct qemud_server *server,
+ struct qemud_client *client,
+ struct qemud_client_message *msg)
{
int ret;
remote_error rerr;
+ bool qemu_call;
DEBUG("prog=%d ver=%d type=%d status=%d serial=%d proc=%d",
msg->hdr.prog, msg->hdr.vers, msg->hdr.type,
@@ -370,22 +374,33 @@ remoteDispatchClientRequest (struct qemud_server *server,
memset(&rerr, 0, sizeof rerr);
/* Check version, etc. */
- if (msg->hdr.prog != REMOTE_PROGRAM) {
+ if (msg->hdr.prog == REMOTE_PROGRAM)
+ qemu_call = false;
+ else if (msg->hdr.prog == QEMU_PROGRAM)
+ qemu_call = true;
+ else {
remoteDispatchFormatError (&rerr,
- _("program mismatch (actual %x, expected
%x)"),
- msg->hdr.prog, REMOTE_PROGRAM);
+ _("program mismatch (actual %x, expected %x or
%x)"),
+ msg->hdr.prog, REMOTE_PROGRAM, QEMU_PROGRAM);
goto error;
}
- if (msg->hdr.vers != REMOTE_PROTOCOL_VERSION) {
+
+ if (!qemu_call && msg->hdr.vers != REMOTE_PROTOCOL_VERSION) {
remoteDispatchFormatError (&rerr,
_("version mismatch (actual %x, expected
%x)"),
msg->hdr.vers, REMOTE_PROTOCOL_VERSION);
goto error;
}
+ else if (qemu_call && msg->hdr.vers != QEMU_PROTOCOL_VERSION) {
+ remoteDispatchFormatError (&rerr,
+ _("version mismatch (actual %x, expected
%x)"),
+ msg->hdr.vers, QEMU_PROTOCOL_VERSION);
+ goto error;
+ }
switch (msg->hdr.type) {
case REMOTE_CALL:
- return remoteDispatchClientCall(server, client, msg);
+ return remoteDispatchClientCall(server, client, msg, qemu_call);
case REMOTE_STREAM:
/* Since stream data is non-acked, async, we may continue to received
@@ -427,10 +442,11 @@ error:
*
* Returns 0 if the reply was sent, or -1 upon fatal error
*/
-int
+static int
remoteDispatchClientCall (struct qemud_server *server,
struct qemud_client *client,
- struct qemud_client_message *msg)
+ struct qemud_client_message *msg,
+ bool qemu_protocol)
{
XDR xdr;
remote_error rerr;
@@ -469,7 +485,10 @@ remoteDispatchClientCall (struct qemud_server *server,
}
}
- data = remoteGetDispatchData(msg->hdr.proc);
+ if (qemu_protocol)
+ data = qemuGetDispatchData(msg->hdr.proc);
+ else
+ data = remoteGetDispatchData(msg->hdr.proc);
if (!data) {
remoteDispatchFormatError (&rerr, _("unknown procedure: %d"),
diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index d292681..56b79d6 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -45,6 +45,7 @@
# include <rpc/types.h>
# include <rpc/xdr.h>
# include "remote_protocol.h"
+# include "qemu_protocol.h"
# include "logging.h"
# include "threads.h"
diff --git a/daemon/qemu_dispatch_args.h b/daemon/qemu_dispatch_args.h
new file mode 100644
index 0000000..e278fa4
--- /dev/null
+++ b/daemon/qemu_dispatch_args.h
@@ -0,0 +1,5 @@
+/* Automatically generated by remote_generate_stubs.pl.
+ * Do not edit this file. Any changes you make will be lost.
+ */
+
+ qemu_monitor_command_args val_qemu_monitor_command_args;
diff --git a/daemon/qemu_dispatch_prototypes.h b/daemon/qemu_dispatch_prototypes.h
new file mode 100644
index 0000000..e6c83ba
--- /dev/null
+++ b/daemon/qemu_dispatch_prototypes.h
@@ -0,0 +1,12 @@
+/* Automatically generated by remote_generate_stubs.pl.
+ * Do not edit this file. Any changes you make will be lost.
+ */
+
+static int qemuDispatchMonitorCommand(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ qemu_monitor_command_args *args,
+ qemu_monitor_command_ret *ret);
diff --git a/daemon/qemu_dispatch_ret.h b/daemon/qemu_dispatch_ret.h
new file mode 100644
index 0000000..492dcf9
--- /dev/null
+++ b/daemon/qemu_dispatch_ret.h
@@ -0,0 +1,5 @@
+/* Automatically generated by remote_generate_stubs.pl.
+ * Do not edit this file. Any changes you make will be lost.
+ */
+
+ qemu_monitor_command_ret val_qemu_monitor_command_ret;
diff --git a/daemon/qemu_dispatch_table.h b/daemon/qemu_dispatch_table.h
new file mode 100644
index 0000000..c196a3c
--- /dev/null
+++ b/daemon/qemu_dispatch_table.h
@@ -0,0 +1,14 @@
+/* Automatically generated by remote_generate_stubs.pl.
+ * Do not edit this file. Any changes you make will be lost.
+ */
+
+{ /* (unused) => 0 */
+ .fn = NULL,
+ .args_filter = (xdrproc_t) xdr_void,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
+{ /* MonitorCommand => 1 */
+ .fn = (dispatch_fn) qemuDispatchMonitorCommand,
+ .args_filter = (xdrproc_t) xdr_qemu_monitor_command_args,
+ .ret_filter = (xdrproc_t) xdr_qemu_monitor_command_ret,
+},
diff --git a/daemon/remote.c b/daemon/remote.c
index c54565c..32ebe8b 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -57,6 +57,7 @@
#include "memory.h"
#include "util.h"
#include "stream.h"
+#include "libvirt/libvirt-qemu.h"
#define VIR_FROM_THIS VIR_FROM_REMOTE
#define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
@@ -81,11 +82,16 @@ static void make_nonnull_domain_snapshot
(remote_nonnull_domain_snapshot *snapsh
#include "remote_dispatch_prototypes.h"
+#include "qemu_dispatch_prototypes.h"
static const dispatch_data const dispatch_table[] = {
#include "remote_dispatch_table.h"
};
+static const dispatch_data const qemu_dispatch_table[] = {
+#include "qemu_dispatch_table.h"
+};
+
const dispatch_data const *remoteGetDispatchData(int proc)
{
if (proc >= ARRAY_CARDINALITY(dispatch_table) ||
@@ -96,6 +102,16 @@ const dispatch_data const *remoteGetDispatchData(int proc)
return &(dispatch_table[proc]);
}
+const dispatch_data const *qemuGetDispatchData(int proc)
+{
+ if (proc >= ARRAY_CARDINALITY(qemu_dispatch_table) ||
+ qemu_dispatch_table[proc].fn == NULL) {
+ return NULL;
+ }
+
+ return &(qemu_dispatch_table[proc]);
+}
+
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
@@ -6505,6 +6521,35 @@ remoteDispatchDomainGetBlockInfo (struct qemud_server *server
ATTRIBUTE_UNUSED,
return 0;
}
+static int
+qemuDispatchMonitorCommand (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ qemu_monitor_command_args *args,
+ qemu_monitor_command_ret *ret)
+{
+ virDomainPtr domain;
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainQemuMonitorCommand(domain, args->cmd, &ret->result,
+ args->flags) == -1) {
+ virDomainFree(domain);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ virDomainFree(domain);
+
+ return 0;
+}
+
/*----- Helpers. -----*/
diff --git a/daemon/remote.h b/daemon/remote.h
index 9db7432..fd8d381 100644
--- a/daemon/remote.h
+++ b/daemon/remote.h
@@ -35,6 +35,13 @@ typedef union {
# include "remote_dispatch_ret.h"
} dispatch_ret;
+typedef union {
+# include "qemu_dispatch_args.h"
+} qemu_dispatch_args;
+
+typedef union {
+# include "qemu_dispatch_ret.h"
+} qemu_dispatch_ret;
@@ -67,6 +74,7 @@ typedef struct {
const dispatch_data const *remoteGetDispatchData(int proc);
+const dispatch_data const *qemuGetDispatchData(int proc);
diff --git a/daemon/remote_generate_stubs.pl b/daemon/remote_generate_stubs.pl
index 8b26e3d..a8c4e6d 100755
--- a/daemon/remote_generate_stubs.pl
+++ b/daemon/remote_generate_stubs.pl
@@ -1,7 +1,16 @@
#!/usr/bin/perl -w
#
-# This script parses remote_protocol.x and produces lots of boilerplate
-# code for both ends of the remote connection.
+# This script parses remote_protocol.x or qemu_protocol.x and produces lots of
+# boilerplate code for both ends of the remote connection.
+#
+# The first non-option argument specifies the prefix to be searched for, and
+# output to, the boilerplate code. The second non-option argument is the
+# file you want to operate on. For instance, to generate the dispatch table
+# for both remote_protocol.x and qemu_protocol.x, you would run the
+# following:
+#
+# remote_generate_stubs.pl -c -t remote ../src/remote/remote_protocol.x
+# remote_generate_stubs.pl -t qemu ../src/remote/qemu_protocol.x
#
# By Richard Jones <rjones(a)redhat.com>
@@ -10,8 +19,12 @@ use strict;
use Getopt::Std;
# Command line options.
-our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d);
-getopts ('ptard');
+our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d, $opt_c);
+getopts ('ptardc');
+
+my $structprefix = $ARGV[0];
+my $procprefix = uc $structprefix;
+shift;
# Convert name_of_call to NameOfCall.
sub name_to_ProcName {
@@ -25,47 +38,50 @@ sub name_to_ProcName {
# opinion about the name, args and return type of each RPC.
my ($name, $ProcName, $id, %calls, @calls);
-# REMOTE_PROC_CLOSE has no args or ret.
-$calls{close} = {
- name => "close",
- ProcName => "Close",
- UC_NAME => "CLOSE",
- args => "void",
- ret => "void",
-};
+# only generate a close method if -c was passed
+if ($opt_c) {
+ # REMOTE_PROC_CLOSE has no args or ret.
+ $calls{close} = {
+ name => "close",
+ ProcName => "Close",
+ UC_NAME => "CLOSE",
+ args => "void",
+ ret => "void",
+ };
+}
while (<>) {
- if (/^struct remote_(.*)_args/) {
+ if (/^struct ${structprefix}_(.*)_args/) {
$name = $1;
$ProcName = name_to_ProcName ($name);
- die "duplicate definition of remote_${name}_args"
+ die "duplicate definition of ${structprefix}_${name}_args"
if exists $calls{$name};
$calls{$name} = {
name => $name,
ProcName => $ProcName,
UC_NAME => uc $name,
- args => "remote_${name}_args",
+ args => "${structprefix}_${name}_args",
ret => "void",
};
- } elsif (/^struct remote_(.*)_ret/) {
+ } elsif (/^struct ${structprefix}_(.*)_ret/) {
$name = $1;
$ProcName = name_to_ProcName ($name);
if (exists $calls{$name}) {
- $calls{$name}->{ret} = "remote_${name}_ret";
+ $calls{$name}->{ret} = "${structprefix}_${name}_ret";
} else {
$calls{$name} = {
name => $name,
ProcName => $ProcName,
UC_NAME => uc $name,
args => "void",
- ret => "remote_${name}_ret"
+ ret => "${structprefix}_${name}_ret"
}
}
- } elsif (/^struct remote_(.*)_msg/) {
+ } elsif (/^struct ${structprefix}_(.*)_msg/) {
$name = $1;
$ProcName = name_to_ProcName ($name);
@@ -73,9 +89,9 @@ while (<>) {
name => $name,
ProcName => $ProcName,
UC_NAME => uc $name,
- msg => "remote_${name}_msg"
+ msg => "${structprefix}_${name}_msg"
}
- } elsif (/^\s*REMOTE_PROC_(.*?)\s+=\s+(\d+),?$/) {
+ } elsif (/^\s*${procprefix}_PROC_(.*?)\s+=\s+(\d+),?$/) {
$name = lc $1;
$id = $2;
$ProcName = name_to_ProcName ($name);
@@ -111,7 +127,7 @@ elsif ($opt_p) {
# Skip things which are REMOTE_MESSAGE
next if $calls{$_}->{msg};
- print "static int remoteDispatch$calls{$_}->{ProcName}(\n";
+ print "static int ${structprefix}Dispatch$calls{$_}->{ProcName}(\n";
print " struct qemud_server *server,\n";
print " struct qemud_client *client,\n";
print " virConnectPtr conn,\n";
@@ -152,7 +168,7 @@ elsif ($opt_t) {
for ($id = 0 ; $id <= $#calls ; $id++) {
if (defined $calls[$id] && !$calls[$id]->{msg}) {
print "{ /* $calls[$id]->{ProcName} => $id */\n";
- print " .fn = (dispatch_fn)
remoteDispatch$calls[$id]->{ProcName},\n";
+ print " .fn = (dispatch_fn)
${structprefix}Dispatch$calls[$id]->{ProcName},\n";
if ($calls[$id]->{args} ne "void") {
print " .args_filter = (xdrproc_t) xdr_$calls[$id]->{args},\n";
} else {
diff --git a/src/Makefile.am b/src/Makefile.am
index c13a511..0562cec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -153,7 +153,9 @@ REMOTE_DRIVER_SOURCES = \
gnutls_1_0_compat.h \
remote/remote_driver.c remote/remote_driver.h \
remote/remote_protocol.c \
- remote/remote_protocol.h
+ remote/remote_protocol.h \
+ remote/qemu_protocol.c \
+ remote/qemu_protocol.h
EXTRA_DIST += remote/remote_protocol.x remote/rpcgen_fix.pl
@@ -464,7 +466,7 @@ if HAVE_RPCGEN
# Support for non-GLIB rpcgen is here as a convenience for
# non-Linux people needing to test changes during dev.
#
-rpcgen:
+rpcgen-normal:
rm -f rp.c-t rp.h-t rp.c-t1 rp.c-t2 rp.h-t1
$(RPCGEN) -h -o rp.h-t $(srcdir)/remote/remote_protocol.x
$(RPCGEN) -c -o rp.c-t $(srcdir)/remote/remote_protocol.x
@@ -481,6 +483,37 @@ else
mv -f rp.h-t $(srcdir)/remote/remote_protocol.h
mv -f rp.c-t $(srcdir)/remote/remote_protocol.c
endif
+
+rpcgen-qemu:
+ rm -f rp_qemu.c-t rp_qemu.h-t rp_qemu.c-t1 rp_qemu.c-t2 rp_qemu.h-t1
+ $(RPCGEN) -h -o rp_qemu.h-t $(srcdir)/remote/qemu_protocol.x
+ $(RPCGEN) -c -o rp_qemu.c-t $(srcdir)/remote/qemu_protocol.x
+if HAVE_GLIBC_RPCGEN
+ perl -w $(srcdir)/remote/rpcgen_fix.pl rp_qemu.h-t > rp_qemu.h-t1
+ perl -w $(srcdir)/remote/rpcgen_fix.pl rp_qemu.c-t > rp_qemu.c-t1
+ (echo '#include <config.h>'; cat rp_qemu.c-t1) > rp_qemu.c-t2
+ chmod 0444 rp_qemu.c-t2 rp_qemu.h-t1
+ mv -f rp_qemu.h-t1 $(srcdir)/remote/qemu_protocol.h
+ mv -f rp_qemu.c-t2 $(srcdir)/remote/qemu_protocol.c
+ rm -f rp_qemu.c-t rp_qemu.h-t rp_qemu.c-t1
+else
+ chmod 0444 rp_qemu.c-t rp_qemu.h-t
+ mv -f rp_qemu.h-t $(srcdir)/remote/qemu_protocol.h
+ mv -f rp_qemu.c-t $(srcdir)/remote/qemu_protocol.c
+endif
+
+#
+# Maintainer-only target for re-generating the derived .c/.h source
+# files, which are actually derived from the .x file.
+#
+# For committing protocol changes to GIT, the GLIBC rpcgen *must*
+# be used.
+#
+# Support for non-GLIB rpcgen is here as a convenience for
+# non-Linux people needing to test changes during dev.
+#
+rpcgen: rpcgen-normal rpcgen-qemu
+
endif
remote/remote_protocol.c: remote/remote_protocol.h
diff --git a/src/remote/qemu_protocol.c b/src/remote/qemu_protocol.c
new file mode 100644
index 0000000..81916ed
--- /dev/null
+++ b/src/remote/qemu_protocol.c
@@ -0,0 +1,41 @@
+#include <config.h>
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "./remote/qemu_protocol.h"
+#include "internal.h"
+#include "remote_protocol.h"
+#include <arpa/inet.h>
+
+bool_t
+xdr_qemu_monitor_command_args (XDR *xdrs, qemu_monitor_command_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->cmd))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_qemu_monitor_command_ret (XDR *xdrs, qemu_monitor_command_ret *objp)
+{
+
+ if (!xdr_remote_nonnull_string (xdrs, &objp->result))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_qemu_procedure (XDR *xdrs, qemu_procedure *objp)
+{
+
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return FALSE;
+ return TRUE;
+}
diff --git a/src/remote/qemu_protocol.h b/src/remote/qemu_protocol.h
new file mode 100644
index 0000000..b822187
--- /dev/null
+++ b/src/remote/qemu_protocol.h
@@ -0,0 +1,57 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _RP_QEMU_H_RPCGEN
+#define _RP_QEMU_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "internal.h"
+#include "remote_protocol.h"
+#include <arpa/inet.h>
+
+struct qemu_monitor_command_args {
+ remote_nonnull_domain domain;
+ remote_nonnull_string cmd;
+ int flags;
+};
+typedef struct qemu_monitor_command_args qemu_monitor_command_args;
+
+struct qemu_monitor_command_ret {
+ remote_nonnull_string result;
+};
+typedef struct qemu_monitor_command_ret qemu_monitor_command_ret;
+#define QEMU_PROGRAM 0x20008087
+#define QEMU_PROTOCOL_VERSION 1
+
+enum qemu_procedure {
+ QEMU_PROC_MONITOR_COMMAND = 1,
+};
+typedef enum qemu_procedure qemu_procedure;
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern bool_t xdr_qemu_monitor_command_args (XDR *, qemu_monitor_command_args*);
+extern bool_t xdr_qemu_monitor_command_ret (XDR *, qemu_monitor_command_ret*);
+extern bool_t xdr_qemu_procedure (XDR *, qemu_procedure*);
+
+#else /* K&R C */
+extern bool_t xdr_qemu_monitor_command_args ();
+extern bool_t xdr_qemu_monitor_command_ret ();
+extern bool_t xdr_qemu_procedure ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_RP_QEMU_H_RPCGEN */
diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x
new file mode 100644
index 0000000..1d07895
--- /dev/null
+++ b/src/remote/qemu_protocol.x
@@ -0,0 +1,46 @@
+/* -*- c -*-
+ * qemu_protocol.x: private protocol for communicating between
+ * remote_internal driver and libvirtd. This protocol is
+ * internal and may change at any time.
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Chris Lalancette <clalance(a)redhat.com>
+ */
+
+%#include "internal.h"
+%#include "remote_protocol.h"
+%#include <arpa/inet.h>
+
+/*----- Protocol. -----*/
+struct qemu_monitor_command_args {
+ remote_nonnull_domain domain;
+ remote_nonnull_string cmd;
+ int flags;
+};
+
+struct qemu_monitor_command_ret {
+ remote_nonnull_string result;
+};
+
+/* Define the program number, protocol version and procedure numbers here. */
+const QEMU_PROGRAM = 0x20008087;
+const QEMU_PROTOCOL_VERSION = 1;
+
+enum qemu_procedure {
+ QEMU_PROC_MONITOR_COMMAND = 1
+};
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index b845165..dac9dc4 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -77,6 +77,7 @@
#include "qparams.h"
#include "remote_driver.h"
#include "remote_protocol.h"
+#include "qemu_protocol.h"
#include "memory.h"
#include "util.h"
#include "event.h"
@@ -199,8 +200,9 @@ struct private_data {
};
enum {
- REMOTE_CALL_IN_OPEN = 1,
- REMOTE_CALL_QUIET_MISSING_RPC = 2,
+ REMOTE_CALL_IN_OPEN = (1 << 0),
+ REMOTE_CALL_QUIET_MISSING_RPC = (1 << 1),
+ REMOTE_QEMU_CALL = (1 << 2),
};
@@ -8827,9 +8829,49 @@ done:
/*----------------------------------------------------------------------*/
+static int
+remoteQemuDomainMonitorCommand (virDomainPtr domain, const char *cmd,
+ char **result, unsigned int flags)
+{
+ int rv = -1;
+ qemu_monitor_command_args args;
+ qemu_monitor_command_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain(&args.domain, domain);
+ args.cmd = (char *)cmd;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, REMOTE_QEMU_CALL, QEMU_PROC_MONITOR_COMMAND,
+ (xdrproc_t) xdr_qemu_monitor_command_args, (char *) &args,
+ (xdrproc_t) xdr_qemu_monitor_command_ret, (char *) &ret) == -1)
+ goto done;
+
+ *result = strdup(ret.result);
+ if (*result == NULL) {
+
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ rv = 0;
+
+cleanup:
+ xdr_free ((xdrproc_t) xdr_qemu_monitor_command_ret, (char *) &ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+/*----------------------------------------------------------------------*/
static struct remote_thread_call *
prepareCall(struct private_data *priv,
+ int flags,
int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret)
@@ -8857,8 +8899,14 @@ prepareCall(struct private_data *priv,
rv->ret = ret;
rv->want_reply = 1;
- hdr.prog = REMOTE_PROGRAM;
- hdr.vers = REMOTE_PROTOCOL_VERSION;
+ if (flags & REMOTE_QEMU_CALL) {
+ hdr.prog = QEMU_PROGRAM;
+ hdr.vers = QEMU_PROTOCOL_VERSION;
+ }
+ else {
+ hdr.prog = REMOTE_PROGRAM;
+ hdr.vers = REMOTE_PROTOCOL_VERSION;
+ }
hdr.proc = proc_nr;
hdr.type = REMOTE_CALL;
hdr.serial = rv->serial;
@@ -9205,7 +9253,6 @@ remoteIODecodeMessageLength(struct private_data *priv) {
static int
processCallDispatchReply(virConnectPtr conn, struct private_data *priv,
- int in_open,
remote_message_header *hdr,
XDR *xdr);
@@ -9217,18 +9264,19 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data
*priv,
static int
processCallDispatchStream(virConnectPtr conn, struct private_data *priv,
- int in_open,
remote_message_header *hdr,
XDR *xdr);
static int
processCallDispatch(virConnectPtr conn, struct private_data *priv,
- int in_open) {
+ int flags) {
XDR xdr;
struct remote_message_header hdr;
int len = priv->bufferLength - 4;
int rv = -1;
+ int expectedprog;
+ int expectedvers;
/* Length word has already been read */
priv->bufferOffset = 4;
@@ -9242,35 +9290,40 @@ processCallDispatch(virConnectPtr conn, struct private_data
*priv,
priv->bufferOffset += xdr_getpos(&xdr);
+ expectedprog = REMOTE_PROGRAM;
+ expectedvers = REMOTE_PROTOCOL_VERSION;
+ if (flags & REMOTE_QEMU_CALL) {
+ expectedprog = QEMU_PROGRAM;
+ expectedvers = QEMU_PROTOCOL_VERSION;
+ }
+
/* Check program, version, etc. are what we expect. */
- if (hdr.prog != REMOTE_PROGRAM) {
+ if (hdr.prog != expectedprog) {
remoteError(VIR_ERR_RPC,
_("unknown program (received %x, expected %x)"),
- hdr.prog, REMOTE_PROGRAM);
+ hdr.prog, expectedprog);
return -1;
}
- if (hdr.vers != REMOTE_PROTOCOL_VERSION) {
+ if (hdr.vers != expectedvers) {
remoteError(VIR_ERR_RPC,
_("unknown protocol version (received %x, expected %x)"),
- hdr.vers, REMOTE_PROTOCOL_VERSION);
+ hdr.vers, expectedvers);
return -1;
}
switch (hdr.type) {
case REMOTE_REPLY: /* Normal RPC replies */
- rv = processCallDispatchReply(conn, priv, in_open,
- &hdr, &xdr);
+ rv = processCallDispatchReply(conn, priv, &hdr, &xdr);
break;
case REMOTE_MESSAGE: /* Async notifications */
- rv = processCallDispatchMessage(conn, priv, in_open,
+ rv = processCallDispatchMessage(conn, priv, flags & REMOTE_CALL_IN_OPEN,
&hdr, &xdr);
break;
case REMOTE_STREAM: /* Stream protocol */
- rv = processCallDispatchStream(conn, priv, in_open,
- &hdr, &xdr);
+ rv = processCallDispatchStream(conn, priv, &hdr, &xdr);
break;
default:
@@ -9289,7 +9342,6 @@ processCallDispatch(virConnectPtr conn, struct private_data *priv,
static int
processCallDispatchReply(virConnectPtr conn ATTRIBUTE_UNUSED,
struct private_data *priv,
- int in_open ATTRIBUTE_UNUSED,
remote_message_header *hdr,
XDR *xdr) {
struct remote_thread_call *thecall;
@@ -9409,7 +9461,6 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data
*priv,
static int
processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
struct private_data *priv,
- int in_open ATTRIBUTE_UNUSED,
remote_message_header *hdr,
XDR *xdr) {
struct private_stream_data *privst;
@@ -9515,7 +9566,7 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
static int
remoteIOHandleInput(virConnectPtr conn, struct private_data *priv,
- int in_open)
+ int flags)
{
/* Read as much data as is available, until we get
* EAGAIN
@@ -9542,7 +9593,7 @@ remoteIOHandleInput(virConnectPtr conn, struct private_data *priv,
* next iteration.
*/
} else {
- ret = processCallDispatch(conn, priv, in_open);
+ ret = processCallDispatch(conn, priv, flags);
priv->bufferOffset = priv->bufferLength = 0;
/*
* We've completed one call, so return even
@@ -9565,7 +9616,7 @@ remoteIOHandleInput(virConnectPtr conn, struct private_data *priv,
static int
remoteIOEventLoop(virConnectPtr conn,
struct private_data *priv,
- int in_open,
+ int flags,
struct remote_thread_call *thiscall)
{
struct pollfd fds[2];
@@ -9655,7 +9706,7 @@ remoteIOEventLoop(virConnectPtr conn,
}
if (fds[0].revents & POLLIN) {
- if (remoteIOHandleInput(conn, priv, in_open) < 0)
+ if (remoteIOHandleInput(conn, priv, flags) < 0)
goto error;
}
@@ -9860,9 +9911,7 @@ remoteIO(virConnectPtr conn,
if (priv->watch >= 0)
virEventUpdateHandle(priv->watch, 0);
- rv = remoteIOEventLoop(conn, priv,
- flags & REMOTE_CALL_IN_OPEN ? 1 : 0,
- thiscall);
+ rv = remoteIOEventLoop(conn, priv, flags, thiscall);
if (priv->watch >= 0)
virEventUpdateHandle(priv->watch, VIR_EVENT_HANDLE_READABLE);
@@ -9934,14 +9983,14 @@ cleanup:
*/
static int
call (virConnectPtr conn, struct private_data *priv,
- int flags /* if we are in virConnectOpen */,
+ int flags,
int proc_nr,
xdrproc_t args_filter, char *args,
xdrproc_t ret_filter, char *ret)
{
struct remote_thread_call *thiscall;
- thiscall = prepareCall(priv, proc_nr, args_filter, args,
+ thiscall = prepareCall(priv, flags, proc_nr, args_filter, args,
ret_filter, ret);
if (!thiscall) {
@@ -10269,7 +10318,7 @@ static virDriver remote_driver = {
remoteDomainSnapshotCurrent, /* domainSnapshotCurrent */
remoteDomainRevertToSnapshot, /* domainRevertToSnapshot */
remoteDomainSnapshotDelete, /* domainSnapshotDelete */
- NULL, /* qemuDomainMonitorCommand */
+ remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index 972bf52..f39a685 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -3591,12 +3591,60 @@ xdr_remote_message_status (XDR *xdrs, remote_message_status
*objp)
bool_t
xdr_remote_message_header (XDR *xdrs, remote_message_header *objp)
{
+ register int32_t *buf;
+
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = (int32_t*)XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int (xdrs, &objp->prog))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->vers))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->proc))
+ return FALSE;
+
+ } else {
+ (void)IXDR_PUT_U_INT32(buf, objp->prog);
+ (void)IXDR_PUT_U_INT32(buf, objp->vers);
+ (void)IXDR_PUT_U_INT32(buf, objp->proc);
+ }
+ if (!xdr_remote_message_type (xdrs, &objp->type))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->serial))
+ return FALSE;
+ if (!xdr_remote_message_status (xdrs, &objp->status))
+ return FALSE;
+ return TRUE;
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = (int32_t*)XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int (xdrs, &objp->prog))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->vers))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->proc))
+ return FALSE;
+
+ } else {
+ objp->prog = IXDR_GET_U_LONG(buf);
+ objp->vers = IXDR_GET_U_LONG(buf);
+ objp->proc = IXDR_GET_U_LONG(buf);
+ }
+ if (!xdr_remote_message_type (xdrs, &objp->type))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->serial))
+ return FALSE;
+ if (!xdr_remote_message_status (xdrs, &objp->status))
+ return FALSE;
+ return TRUE;
+ }
if (!xdr_u_int (xdrs, &objp->prog))
return FALSE;
if (!xdr_u_int (xdrs, &objp->vers))
return FALSE;
- if (!xdr_remote_procedure (xdrs, &objp->proc))
+ if (!xdr_u_int (xdrs, &objp->proc))
return FALSE;
if (!xdr_remote_message_type (xdrs, &objp->type))
return FALSE;
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index a600af6..8629b0b 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -2237,7 +2237,7 @@ typedef enum remote_message_status remote_message_status;
struct remote_message_header {
u_int prog;
u_int vers;
- remote_procedure proc;
+ u_int proc;
remote_message_type type;
u_int serial;
remote_message_status status;
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 1ce488c..c3cb7de 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2112,7 +2112,7 @@ const REMOTE_MESSAGE_HEADER_XDR_LEN = 4;
struct remote_message_header {
unsigned prog; /* REMOTE_PROGRAM */
unsigned vers; /* REMOTE_PROTOCOL_VERSION */
- remote_procedure proc; /* REMOTE_PROC_x */
+ unsigned proc; /* REMOTE_PROC_x */
remote_message_type type;
unsigned serial; /* Serial number of message. */
remote_message_status status;
--
1.6.6.1