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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list