This provides an implementation of the virDomainOpenConsole
API for the remote driver client and server.
* daemon/remote.c: Server side impl
* src/remote/remote_driver.c: Client impl
* src/remote/remote_protocol.x: Wire definition
---
daemon/remote.c | 52 +++++++++++++++++
daemon/remote_dispatch_args.h | 1 +
daemon/remote_dispatch_prototypes.h | 8 +++
daemon/remote_dispatch_table.h | 5 ++
src/remote/remote_driver.c | 108 ++++++++++++++++++++++++----------
src/remote/remote_protocol.c | 13 ++++
src/remote/remote_protocol.h | 10 +++
src/remote/remote_protocol.x | 8 ++-
8 files changed, 172 insertions(+), 33 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 118654c..10980db 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -6610,6 +6610,58 @@ qemuDispatchMonitorCommand (struct qemud_server *server
ATTRIBUTE_UNUSED,
}
+static int
+remoteDispatchDomainOpenConsole(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *rerr,
+ remote_domain_open_console_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ int r;
+ struct qemud_client_stream *stream;
+ virDomainPtr dom;
+
+ CHECK_CONN (client);
+
+ dom = get_nonnull_domain (conn, args->domain);
+ if (dom == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ stream = remoteCreateClientStream(conn, hdr);
+ if (!stream) {
+ virDomainFree(dom);
+ remoteDispatchOOMError(rerr);
+ return -1;
+ }
+
+ r = virDomainOpenConsole(dom,
+ args->devname ? *args->devname : NULL,
+ stream->st,
+ args->flags);
+ if (r == -1) {
+ virDomainFree(dom);
+ remoteFreeClientStream(client, stream);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (remoteAddClientStream(client, stream, 1) < 0) {
+ virDomainFree(dom);
+ remoteDispatchConnError(rerr, conn);
+ virStreamAbort(stream->st);
+ remoteFreeClientStream(client, stream);
+ return -1;
+ }
+
+ virDomainFree(dom);
+ return 0;
+}
+
+
/*----- Helpers. -----*/
/* get_nonnull_domain and get_nonnull_network turn an on-wire
diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h
index ee95043..23b6293 100644
--- a/daemon/remote_dispatch_args.h
+++ b/daemon/remote_dispatch_args.h
@@ -165,3 +165,4 @@
remote_domain_snapshot_delete_args val_remote_domain_snapshot_delete_args;
remote_domain_get_block_info_args val_remote_domain_get_block_info_args;
remote_domain_create_with_flags_args val_remote_domain_create_with_flags_args;
+ remote_domain_open_console_args val_remote_domain_open_console_args;
diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h
index cf1a0f9..b744c28 100644
--- a/daemon/remote_dispatch_prototypes.h
+++ b/daemon/remote_dispatch_prototypes.h
@@ -450,6 +450,14 @@ static int remoteDispatchDomainMigrateSetMaxDowntime(
remote_error *err,
remote_domain_migrate_set_max_downtime_args *args,
void *ret);
+static int remoteDispatchDomainOpenConsole(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_open_console_args *args,
+ void *ret);
static int remoteDispatchDomainPinVcpu(
struct qemud_server *server,
struct qemud_client *client,
diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h
index ef00edd..73ec505 100644
--- a/daemon/remote_dispatch_table.h
+++ b/daemon/remote_dispatch_table.h
@@ -987,3 +987,8 @@
.args_filter = (xdrproc_t) xdr_remote_domain_create_with_flags_args,
.ret_filter = (xdrproc_t) xdr_remote_domain_create_with_flags_ret,
},
+{ /* DomainOpenConsole => 197 */
+ .fn = (dispatch_fn) remoteDispatchDomainOpenConsole,
+ .args_filter = (xdrproc_t) xdr_remote_domain_open_console_args,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 860ae46..a3608d7 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -7974,11 +7974,16 @@ remoteStreamEventTimerUpdate(struct private_stream_data *privst)
if (!privst->cb)
return;
- if (!privst->cbEvents)
- virEventUpdateTimeout(privst->cbTimer, -1);
- else if (privst->incoming &&
- (privst->cbEvents & VIR_STREAM_EVENT_READABLE))
+ VIR_DEBUG("Check timer offset=%d %d", privst->incomingOffset,
privst->cbEvents);
+ if ((privst->incomingOffset &&
+ (privst->cbEvents & VIR_STREAM_EVENT_READABLE)) ||
+ (privst->cbEvents & VIR_STREAM_EVENT_WRITABLE)) {
+ VIR_DEBUG0("Enabling event timer");
virEventUpdateTimeout(privst->cbTimer, 0);
+ } else {
+ VIR_DEBUG0("Disabling event timer");
+ virEventUpdateTimeout(privst->cbTimer, -1);
+ }
}
@@ -8084,7 +8089,7 @@ remoteStreamHasError(virStreamPtr st) {
return 0;
}
- VIR_WARN0("Raising async error");
+ VIR_DEBUG0("Raising async error");
virRaiseErrorFull(st->conn,
__FILE__, __FUNCTION__, __LINE__,
privst->err.domain,
@@ -8244,24 +8249,33 @@ remoteStreamEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
virStreamPtr st = opaque;
struct private_data *priv = st->conn->privateData;
struct private_stream_data *privst = st->privateData;
+ int events = 0;
remoteDriverLock(priv);
+
if (privst->cb &&
(privst->cbEvents & VIR_STREAM_EVENT_READABLE) &&
- privst->incomingOffset) {
+ privst->incomingOffset)
+ events |= VIR_STREAM_EVENT_READABLE;
+ if (privst->cb &&
+ (privst->cbEvents & VIR_STREAM_EVENT_WRITABLE))
+ events |= VIR_STREAM_EVENT_WRITABLE;
+ VIR_DEBUG("Got Timer dispatch %d %d offset=%d", events,
privst->cbEvents, privst->incomingOffset);
+ if (events) {
virStreamEventCallback cb = privst->cb;
void *cbOpaque = privst->cbOpaque;
virFreeCallback cbFree = privst->cbFree;
privst->cbDispatch = 1;
remoteDriverUnlock(priv);
- (cb)(st, VIR_STREAM_EVENT_READABLE, cbOpaque);
+ (cb)(st, events, cbOpaque);
remoteDriverLock(priv);
privst->cbDispatch = 0;
if (!privst->cb && cbFree)
(cbFree)(cbOpaque);
}
+
remoteDriverUnlock(priv);
}
@@ -8287,12 +8301,6 @@ remoteStreamEventAddCallback(virStreamPtr st,
remoteDriverLock(priv);
- if (events & ~VIR_STREAM_EVENT_READABLE) {
- remoteError(VIR_ERR_INTERNAL_ERROR,
- _("unsupported stream events %d"), events);
- goto cleanup;
- }
-
if (privst->cb) {
remoteError(VIR_ERR_INTERNAL_ERROR,
_("multiple stream callbacks not supported"));
@@ -8314,6 +8322,8 @@ remoteStreamEventAddCallback(virStreamPtr st,
privst->cbFree = ff;
privst->cbEvents = events;
+ remoteStreamEventTimerUpdate(privst);
+
ret = 0;
cleanup:
@@ -8331,12 +8341,6 @@ remoteStreamEventUpdateCallback(virStreamPtr st,
remoteDriverLock(priv);
- if (events & ~VIR_STREAM_EVENT_READABLE) {
- remoteError(VIR_ERR_INTERNAL_ERROR,
- _("unsupported stream events %d"), events);
- goto cleanup;
- }
-
if (!privst->cb) {
remoteError(VIR_ERR_INTERNAL_ERROR,
_("no stream callback registered"));
@@ -9018,6 +9022,46 @@ done:
}
+static int
+remoteDomainOpenConsole(virDomainPtr dom,
+ const char *devname,
+ virStreamPtr st,
+ unsigned int flags)
+{
+ struct private_data *priv = dom->conn->privateData;
+ struct private_stream_data *privst = NULL;
+ int rv = -1;
+ remote_domain_open_console_args args;
+
+ remoteDriverLock(priv);
+
+ if (!(privst = remoteStreamOpen(st, 1, REMOTE_PROC_DOMAIN_OPEN_CONSOLE,
priv->counter)))
+ goto done;
+
+ st->driver = &remoteStreamDrv;
+ st->privateData = privst;
+
+ make_nonnull_domain (&args.domain, dom);
+ args.devname = devname ? (char **)&devname : NULL;
+ args.flags = flags;
+
+ if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_OPEN_CONSOLE,
+ (xdrproc_t) xdr_remote_domain_open_console_args, (char *) &args,
+ (xdrproc_t) xdr_void, NULL) == -1) {
+ remoteStreamRelease(st);
+ goto done;
+ }
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+
+ return rv;
+
+}
+
+
/*----------------------------------------------------------------------*/
static int
@@ -9665,8 +9709,8 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
privst = privst->next;
if (!privst) {
- VIR_WARN("No registered stream matching serial=%d, proc=%d",
- hdr->serial, hdr->proc);
+ VIR_DEBUG("No registered stream matching serial=%d, proc=%d",
+ hdr->serial, hdr->proc);
return -1;
}
@@ -9685,7 +9729,7 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
case REMOTE_CONTINUE: {
int avail = privst->incomingLength - privst->incomingOffset;
int need = priv->bufferLength - priv->bufferOffset;
- VIR_WARN0("Got a stream data packet");
+ VIR_DEBUG0("Got a stream data packet");
/* XXX flag stream as complete somwhere if need==0 */
@@ -9693,7 +9737,7 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
int extra = need - avail;
if (VIR_REALLOC_N(privst->incoming,
privst->incomingLength + extra) < 0) {
- VIR_WARN0("Out of memory");
+ VIR_DEBUG0("Out of memory handling stream data");
return -1;
}
privst->incomingLength += extra;
@@ -9705,19 +9749,19 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
privst->incomingOffset += (priv->bufferLength - priv->bufferOffset);
if (thecall && thecall->want_reply) {
- VIR_WARN("Got sync data packet offset=%d",
privst->incomingOffset);
+ VIR_DEBUG("Got sync data packet offset=%d",
privst->incomingOffset);
thecall->mode = REMOTE_MODE_COMPLETE;
} else {
- VIR_WARN("Got aysnc data packet offset=%d",
privst->incomingOffset);
+ VIR_DEBUG("Got aysnc data packet offset=%d",
privst->incomingOffset);
remoteStreamEventTimerUpdate(privst);
}
return 0;
}
case REMOTE_OK:
- VIR_WARN0("Got a synchronous confirm");
+ VIR_DEBUG0("Got a synchronous confirm");
if (!thecall) {
- VIR_WARN0("Got unexpected stream finish confirmation");
+ VIR_DEBUG0("Got unexpected stream finish confirmation");
return -1;
}
thecall->mode = REMOTE_MODE_COMPLETE;
@@ -9725,7 +9769,7 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
case REMOTE_ERROR:
if (thecall && thecall->want_reply) {
- VIR_WARN0("Got a synchronous error");
+ VIR_DEBUG0("Got a synchronous error");
/* Give the error straight to this call */
memset (&thecall->err, 0, sizeof thecall->err);
if (!xdr_remote_error (xdr, &thecall->err)) {
@@ -9734,16 +9778,16 @@ processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
}
thecall->mode = REMOTE_MODE_ERROR;
} else {
- VIR_WARN0("Got a asynchronous error");
+ VIR_DEBUG0("Got a asynchronous error");
/* No call, so queue the error against the stream */
if (privst->has_error) {
- VIR_WARN0("Got unexpected duplicate stream error");
+ VIR_DEBUG0("Got unexpected duplicate stream error");
return -1;
}
privst->has_error = 1;
memset (&privst->err, 0, sizeof privst->err);
if (!xdr_remote_error (xdr, &privst->err)) {
- VIR_WARN0("Failed to unmarshall error");
+ VIR_DEBUG0("Failed to unmarshall error");
return -1;
}
}
@@ -10509,7 +10553,7 @@ static virDriver remote_driver = {
remoteDomainRevertToSnapshot, /* domainRevertToSnapshot */
remoteDomainSnapshotDelete, /* domainSnapshotDelete */
remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
- NULL, /* domainOpenConsole */
+ remoteDomainOpenConsole, /* domainOpenConsole */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index 2483004..0a3b914 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -3588,6 +3588,19 @@ xdr_remote_domain_snapshot_delete_args (XDR *xdrs,
remote_domain_snapshot_delete
}
bool_t
+xdr_remote_domain_open_console_args (XDR *xdrs, remote_domain_open_console_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_remote_string (xdrs, &objp->devname))
+ return FALSE;
+ if (!xdr_u_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
{
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index afe9287..1b90d21 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -2033,6 +2033,13 @@ struct remote_domain_snapshot_delete_args {
int flags;
};
typedef struct remote_domain_snapshot_delete_args remote_domain_snapshot_delete_args;
+
+struct remote_domain_open_console_args {
+ remote_nonnull_domain domain;
+ remote_string devname;
+ u_int flags;
+};
+typedef struct remote_domain_open_console_args remote_domain_open_console_args;
#define REMOTE_PROGRAM 0x20008086
#define REMOTE_PROTOCOL_VERSION 1
@@ -2233,6 +2240,7 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194,
REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195,
REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196,
+ REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 197,
};
typedef enum remote_procedure remote_procedure;
@@ -2594,6 +2602,7 @@ extern bool_t xdr_remote_domain_snapshot_current_args (XDR *,
remote_domain_sna
extern bool_t xdr_remote_domain_snapshot_current_ret (XDR *,
remote_domain_snapshot_current_ret*);
extern bool_t xdr_remote_domain_revert_to_snapshot_args (XDR *,
remote_domain_revert_to_snapshot_args*);
extern bool_t xdr_remote_domain_snapshot_delete_args (XDR *,
remote_domain_snapshot_delete_args*);
+extern bool_t xdr_remote_domain_open_console_args (XDR *,
remote_domain_open_console_args*);
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
extern bool_t xdr_remote_message_type (XDR *, remote_message_type*);
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
@@ -2929,6 +2938,7 @@ extern bool_t xdr_remote_domain_snapshot_current_args ();
extern bool_t xdr_remote_domain_snapshot_current_ret ();
extern bool_t xdr_remote_domain_revert_to_snapshot_args ();
extern bool_t xdr_remote_domain_snapshot_delete_args ();
+extern bool_t xdr_remote_domain_open_console_args ();
extern bool_t xdr_remote_procedure ();
extern bool_t xdr_remote_message_type ();
extern bool_t xdr_remote_message_status ();
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 8af469c..5d10901 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -1798,6 +1798,11 @@ struct remote_domain_snapshot_delete_args {
int flags;
};
+struct remote_domain_open_console_args {
+ remote_nonnull_domain domain;
+ remote_string devname;
+ unsigned int flags;
+};
/*----- Protocol. -----*/
@@ -2020,7 +2025,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194,
REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195,
- REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196
+ REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196,
+ REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 197
/*
* Notice how the entries are grouped in sets of 10 ?
--
1.7.2.1