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 | 82 +++++++++++++++++++++++++++-------- src/remote/remote_protocol.c | 13 ++++++ src/remote/remote_protocol.h | 10 ++++ src/remote/remote_protocol.x | 9 +++- src/remote_protocol-structs | 5 ++ 9 files changed, 165 insertions(+), 20 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 3cf3886..1660815 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -6907,6 +6907,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 9583e9c..971af80 100644 --- a/daemon/remote_dispatch_args.h +++ b/daemon/remote_dispatch_args.h @@ -169,3 +169,4 @@ remote_domain_get_memory_parameters_args val_remote_domain_get_memory_parameters_args; remote_domain_set_vcpus_flags_args val_remote_domain_set_vcpus_flags_args; remote_domain_get_vcpus_flags_args val_remote_domain_get_vcpus_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 6b35851..15c7ec7 100644 --- a/daemon/remote_dispatch_prototypes.h +++ b/daemon/remote_dispatch_prototypes.h @@ -466,6 +466,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 dd2adc7..4cfa1b1 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -1007,3 +1007,8 @@ .args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args, .ret_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret, }, +{ /* DomainOpenConsole => 201 */ + .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 2ad5ef7..57aec96 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8158,11 +8158,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); + } } @@ -8428,24 +8433,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); } @@ -8471,12 +8485,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")); @@ -8498,6 +8506,8 @@ remoteStreamEventAddCallback(virStreamPtr st, privst->cbFree = ff; privst->cbEvents = events; + remoteStreamEventTimerUpdate(privst); + ret = 0; cleanup: @@ -8515,12 +8525,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")); @@ -9202,6 +9206,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 @@ -10697,7 +10741,7 @@ static virDriver remote_driver = { remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ remoteDomainSetMemoryParameters, /* domainSetMemoryParameters */ remoteDomainGetMemoryParameters, /* domainGetMemoryParameters */ - NULL, /* domainOpenConsole */ + remoteDomainOpenConsole, /* domainOpenConsole */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index 38ea050..41f5e7d 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -3709,6 +3709,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 d75e76c..8dc89a5 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -2097,6 +2097,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 @@ -2301,6 +2308,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, + REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201, }; typedef enum remote_procedure remote_procedure; @@ -2670,6 +2678,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*); @@ -3013,6 +3022,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 d57e6d0..e84afe5 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1853,6 +1853,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. -----*/ @@ -2079,7 +2084,9 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS = 197, REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199, - REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200 + REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, + + REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201 /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index d505886..3054bbf 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1352,6 +1352,11 @@ struct remote_domain_snapshot_delete_args { remote_nonnull_domain_snapshot snap; int flags; }; +struct remote_domain_open_console_args { + remote_nonnull_domain domain; + remote_string devname; + u_int flags; +}; struct remote_message_header { u_int prog; u_int vers; -- 1.7.2.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list