diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index e737e39d38..5dd0e78b2f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5360,6 +5360,14 @@ qemu-kvm -net nic,model=? /dev/null of the first forward dev will be used.

+
socket since 1.3.6 (QEMU only)
+
+

+ This listen type tells a graphics server to listen on unix socket. + Attribute socket contains a path to unix socket. If this + attribute is omitted libvirt will generate this path for you. +

+

Video devices

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d14c1c5ecf..f0640cce10 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2976,6 +2976,16 @@ + + + socket + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 133c2a3ea9..0adf885584 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -561,7 +561,8 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST, VIR_ENUM_IMPL(virDomainGraphicsListen, VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST, "none", "address", - "network") + "network", + "socket") VIR_ENUM_IMPL(virDomainGraphicsAuthConnected, VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST, @@ -1229,6 +1230,7 @@ virDomainGraphicsListenDefClear(virDomainGraphicsListenDefPtr def) VIR_FREE(def->address); VIR_FREE(def->network); + VIR_FREE(def->socket); return; } @@ -10895,6 +10897,7 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node, /** * virDomainGraphicsListenDefParseXML: * @def: listen def pointer to be filled + * @graphics: graphics def pointer * @node: xml node of element * @parent: xml node of element * @flags: bit-wise or of VIR_DOMAIN_DEF_PARSE_* @@ -10906,6 +10909,7 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node, */ static int virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDefPtr def, + virDomainGraphicsDefPtr graphics, xmlNodePtr node, xmlNodePtr parent, unsigned int flags) @@ -10914,8 +10918,10 @@ virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDefPtr def, char *type = virXMLPropString(node, "type"); char *address = virXMLPropString(node, "address"); char *network = virXMLPropString(node, "network"); + char *socket = virXMLPropString(node, "socket"); char *fromConfig = virXMLPropString(node, "fromConfig"); char *addressCompat = NULL; + const char *graphicsType = virDomainGraphicsTypeToString(graphics->type); int tmp, typeVal; if (parent) @@ -10934,6 +10940,13 @@ virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDefPtr def, } def->type = typeVal; + if (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("listen type 'socket' is not available for " + "graphics type '%s'"), graphicsType); + goto error; + } + if (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) { if (address && addressCompat && STRNEQ(address, addressCompat)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -10968,6 +10981,17 @@ virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDefPtr def, network = NULL; } + if (socket && socket[0]) { + if (def->type != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'socket' attribute is valid only for listen " + "type 'socket'")); + goto error; + } + def->socket = socket; + socket = NULL; + } + if (fromConfig && flags & VIR_DOMAIN_DEF_PARSE_STATUS) { if (virStrToLong_i(fromConfig, NULL, 10, &tmp) < 0) { @@ -10986,6 +11010,7 @@ virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDefPtr def, VIR_FREE(type); VIR_FREE(address); VIR_FREE(network); + VIR_FREE(socket); VIR_FREE(fromConfig); VIR_FREE(addressCompat); return ret; @@ -11025,7 +11050,7 @@ virDomainGraphicsListensParseXML(virDomainGraphicsDefPtr def, goto error; for (i = 0; i < nListens; i++) { - if (virDomainGraphicsListenDefParseXML(&def->listens[i], + if (virDomainGraphicsListenDefParseXML(&def->listens[i], def, listenNodes[i], i == 0 ? node : NULL, flags) < 0) @@ -21707,6 +21732,13 @@ virDomainGraphicsListenDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " network='%s'", def->network); } + if (def->socket && + def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET && + !(def->autoGenerated && + (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))) { + virBufferEscapeString(buf, " socket='%s'", def->socket); + } + if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS) virBufferAsprintf(buf, " fromConfig='%d'", def->fromConfig); @@ -24208,6 +24240,30 @@ virDomainGraphicsListenAppendAddress(virDomainGraphicsDefPtr def, } +int +virDomainGraphicsListenAppendSocket(virDomainGraphicsDefPtr def, + const char *socket) +{ + virDomainGraphicsListenDef listen; + + memset(&listen, 0, sizeof(listen)); + + listen.type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET; + + if (VIR_STRDUP(listen.socket, socket) < 0) + goto error; + + if (VIR_APPEND_ELEMENT_COPY(def->listens, def->nListens, listen) < 0) + goto error; + + return 0; + + error: + VIR_FREE(listen.socket); + return -1; +} + + /** * virDomainNetFind: * @def: domain's def diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d1fc4b7567..05dbfc2943 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1418,6 +1418,7 @@ typedef enum { VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE = 0, VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS, VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK, + VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET, VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST } virDomainGraphicsListenType; @@ -1434,7 +1435,9 @@ struct _virDomainGraphicsListenDef { virDomainGraphicsListenType type; char *address; char *network; + char *socket; bool fromConfig; /* true if the @address is config file originated */ + bool autoGenerated; }; struct _virDomainGraphicsDef { @@ -2751,6 +2754,9 @@ virDomainGraphicsGetListen(virDomainGraphicsDefPtr def, size_t i); int virDomainGraphicsListenAppendAddress(virDomainGraphicsDefPtr def, const char *address) ATTRIBUTE_NONNULL(1); +int virDomainGraphicsListenAppendSocket(virDomainGraphicsDefPtr def, + const char *socket) + ATTRIBUTE_NONNULL(1); int virDomainNetGetActualType(virDomainNetDefPtr iface); const char *virDomainNetGetActualBridgeName(virDomainNetDefPtr iface); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9737ddb8a7..42f664c637 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -307,6 +307,7 @@ virDomainGraphicsAuthConnectedTypeToString; virDomainGraphicsDefFree; virDomainGraphicsGetListen; virDomainGraphicsListenAppendAddress; +virDomainGraphicsListenAppendSocket; virDomainGraphicsSpiceChannelModeTypeFromString; virDomainGraphicsSpiceChannelModeTypeToString; virDomainGraphicsSpiceChannelNameTypeFromString; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6fbeb32253..58156c6a43 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2624,6 +2624,15 @@ qemuDomainChangeGraphics(virQEMUDriverPtr driver, break; + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET: + if (STRNEQ_NULLABLE(newlisten->socket, oldlisten->socket)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("cannot change listen socket setting " + "on '%s' graphics"), type); + goto cleanup; + } + break; + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE: case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST: /* nada */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 1c1a1bff80..89d963dbce 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4080,6 +4080,15 @@ qemuProcessGraphicsSetupListen(virQEMUDriverConfigPtr cfg, return -1; break; + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET: + if (!glisten->socket) { + if (virAsprintf(&glisten->socket, "%s/%s.sock", + priv->libDir, type) < 0) + return -1; + glisten->autoGenerated = true; + } + break; + case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE: case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST: break; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 6b0685c93b..b6cde42c8e 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1007,10 +1007,22 @@ get_files(vahControl * ctl) goto cleanup; for (i = 0; i < ctl->def->ngraphics; i++) { - if (ctl->def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && - ctl->def->graphics[i]->data.vnc.socket && - vah_add_file(&buf, ctl->def->graphics[i]->data.vnc.socket, "w")) + virDomainGraphicsDefPtr graphics = ctl->def->graphics[i]; + size_t n; + + if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && + graphics->data.vnc.socket && + vah_add_file(&buf, graphics->data.vnc.socket, "w")) goto cleanup; + + for (n = 0; n < graphics->nListens; n++) { + virDomainGraphicsListenDef listenObj = graphics->listens[n]; + + if (listenObj.type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET && + listenObj.socket && + vah_add_file(&buf, listenObj.socket, "rw")) + goto cleanup; + } } if (ctl->def->ngraphics == 1 &&