Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
docs/formatdomain.html.in | 8 ++++++
docs/schemas/domaincommon.rng | 10 ++++++++
src/conf/domain_conf.c | 60 +++++++++++++++++++++++++++++++++++++++++--
src/conf/domain_conf.h | 6 +++++
src/libvirt_private.syms | 1 +
src/qemu/qemu_hotplug.c | 9 +++++++
src/qemu/qemu_process.c | 9 +++++++
src/security/virt-aa-helper.c | 15 ++++++++---
8 files changed, 112 insertions(+), 6 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e737e39..5dd0e78 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.
</p>
</dd>
+ <dt><code>socket</code> <span class="since">since
1.3.6 (QEMU only)</span></dt>
+ <dd>
+ <p>
+ This listen type tells a graphics server to listen on unix socket.
+ Attribute <code>socket</code> contains a path to unix socket. If
this
+ attribute is omitted libvirt will generate this path for you.
+ </p>
+ </dd>
</dl>
<h4><a name="elementsVideo">Video devices</a></h4>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d14c1c5..f0640cc 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2976,6 +2976,16 @@
</attribute>
</optional>
</group>
+ <group>
+ <attribute name="type">
+ <value>socket</value>
+ </attribute>
+ <optional>
+ <attribute name="socket">
+ <ref name="absFilePath"/>
+ </attribute>
+ </optional>
+ </group>
</choice>
</element>
</zeroOrMore>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 133c2a3..0adf885 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 <listen/> element
* @parent: xml node of <graphics/> 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 d1fc4b7..05dbfc2 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 27ad7ff..d3e761a 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 6ce0a84..64f34ac 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2620,6 +2620,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 71ac08c..5e66c31 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 6b0685c..9eafaee 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1007,10 +1007,17 @@ 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"))
- goto cleanup;
+ virDomainGraphicsDefPtr graphics = ctl->def->graphics[i];
+ size_t n;
+
+ 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 &&
--
2.8.3