diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c9d8b726e0..859f3fdf50 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1350,7 +1350,11 @@ qemu-kvm -net nic,model=? /dev/null in clear text. The keymap attribute specifies the keymap to use. It is possible to set a limit on the validity of the password be giving an timestamp passwdValidTo='2010-04-09T15:51:00' - assumed to be in UTC. NB, this may not be supported by all hypervisors. + assumed to be in UTC. NB, this may not be supported by all hypervisors.
+
+ Rather than using listen/port, QEMU supports a socket + attribute for listening on a unix domain socket path. + Since 0.8.8
"spice"
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 9b977b5d8c..d4756e6e92 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1127,24 +1127,35 @@ vnc - - - - - - - - - yes - no - - - - - - - - + + + + + + + + + + + yes + no + + + + + + + + + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5481313087..699fee750a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -477,6 +477,7 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) switch (def->type) { case VIR_DOMAIN_GRAPHICS_TYPE_VNC: VIR_FREE(def->data.vnc.listenAddr); + VIR_FREE(def->data.vnc.socket); VIR_FREE(def->data.vnc.keymap); virDomainGraphicsAuthDefClear(&def->data.vnc.auth); break; @@ -3495,6 +3496,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } def->data.vnc.listenAddr = virXMLPropString(node, "listen"); + def->data.vnc.socket = virXMLPropString(node, "socket"); def->data.vnc.keymap = virXMLPropString(node, "keymap"); if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0) @@ -7081,19 +7083,25 @@ virDomainGraphicsDefFormat(virBufferPtr buf, switch (def->type) { case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - if (def->data.vnc.port && - (!def->data.vnc.autoport || !(flags & VIR_DOMAIN_XML_INACTIVE))) - virBufferVSprintf(buf, " port='%d'", - def->data.vnc.port); - else if (def->data.vnc.autoport) - virBufferAddLit(buf, " port='-1'"); + if (def->data.vnc.socket) { + if (def->data.vnc.socket) + virBufferVSprintf(buf, " socket='%s'", + def->data.vnc.socket); + } else { + if (def->data.vnc.port && + (!def->data.vnc.autoport || !(flags & VIR_DOMAIN_XML_INACTIVE))) + virBufferVSprintf(buf, " port='%d'", + def->data.vnc.port); + else if (def->data.vnc.autoport) + virBufferAddLit(buf, " port='-1'"); - virBufferVSprintf(buf, " autoport='%s'", - def->data.vnc.autoport ? "yes" : "no"); + virBufferVSprintf(buf, " autoport='%s'", + def->data.vnc.autoport ? "yes" : "no"); - if (def->data.vnc.listenAddr) - virBufferVSprintf(buf, " listen='%s'", - def->data.vnc.listenAddr); + if (def->data.vnc.listenAddr) + virBufferVSprintf(buf, " listen='%s'", + def->data.vnc.listenAddr); + } if (def->data.vnc.keymap) virBufferEscapeString(buf, " keymap='%s'", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 409a2fe784..3b00ba0cd8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -596,6 +596,7 @@ struct _virDomainGraphicsDef { unsigned int autoport :1; char *listenAddr; char *keymap; + char *socket; virDomainGraphicsAuthDef auth; } vnc; struct { diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index b969ecc353..58500e33b8 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3560,7 +3560,11 @@ qemuBuildCommandLine(virConnectPtr conn, def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) { virBuffer opt = VIR_BUFFER_INITIALIZER; - if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) { + if (def->graphics[0]->data.vnc.socket) { + virBufferVSprintf(&opt, "unix:%s", + def->graphics[0]->data.vnc.socket); + + } else if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) { if (def->graphics[0]->data.vnc.listenAddr) virBufferAdd(&opt, def->graphics[0]->data.vnc.listenAddr, -1); else if (driver->vncListen) @@ -3569,6 +3573,12 @@ qemuBuildCommandLine(virConnectPtr conn, virBufferVSprintf(&opt, ":%d", def->graphics[0]->data.vnc.port - 5900); + } else { + virBufferVSprintf(&opt, "%d", + def->graphics[0]->data.vnc.port - 5900); + } + + if (qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) { if (def->graphics[0]->data.vnc.auth.passwd || driver->vncPassword) virBufferAddLit(&opt, ",password"); @@ -3593,9 +3603,6 @@ qemuBuildCommandLine(virConnectPtr conn, /* TODO: Support ACLs later */ } - } else { - virBufferVSprintf(&opt, "%d", - def->graphics[0]->data.vnc.port - 5900); } virCommandAddArg(cmd, "-vnc"); @@ -5296,24 +5303,33 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, goto no_memory; vnc->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC; - tmp = strchr(val, ':'); - if (tmp) { - char *opts; - if (virStrToLong_i(tmp+1, &opts, 10, &vnc->data.vnc.port) < 0) { - VIR_FREE(vnc); - qemuReportError(VIR_ERR_INTERNAL_ERROR, \ - _("cannot parse VNC port '%s'"), tmp+1); - goto error; - } - vnc->data.vnc.listenAddr = strndup(val, tmp-val); - if (!vnc->data.vnc.listenAddr) { + if (STRPREFIX(val, "unix:")) { + vnc->data.vnc.socket = strdup(val + 5); + if (!vnc->data.vnc.socket) { VIR_FREE(vnc); goto no_memory; } - vnc->data.vnc.port += 5900; - vnc->data.vnc.autoport = 0; } else { - vnc->data.vnc.autoport = 1; + tmp = strchr(val, ':'); + if (tmp) { + char *opts; + if (virStrToLong_i(tmp+1, &opts, 10, + &vnc->data.vnc.port) < 0) { + VIR_FREE(vnc); + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse VNC port '%s'"), tmp+1); + goto error; + } + vnc->data.vnc.listenAddr = strndup(val, tmp-val); + if (!vnc->data.vnc.listenAddr) { + VIR_FREE(vnc); + goto no_memory; + } + vnc->data.vnc.port += 5900; + vnc->data.vnc.autoport = 0; + } else { + vnc->data.vnc.autoport = 1; + } } if (VIR_REALLOC_N(def->graphics, def->ngraphics+1) < 0) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5a4466453b..34cc29fbaf 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2674,6 +2674,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, if (vm->def->ngraphics == 1) { if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && + !vm->def->graphics[0]->data.vnc.socket && vm->def->graphics[0]->data.vnc.autoport) { int port = qemudNextFreePort(driver, QEMU_VNC_PORT_MIN); if (port < 0) { diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 8338af3318..7499ba06fe 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -178,6 +178,7 @@ mymain(int argc, char **argv) DO_TEST("disk-drive-network-sheepdog"); DO_TEST("disk-usb"); DO_TEST("graphics-vnc"); + DO_TEST("graphics-vnc-socket"); driver.vncSASL = 1; driver.vncSASLdir = strdup("/root/.sasl2"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-socket.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-socket.args new file mode 100644 index 0000000000..055c562e9b --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-socket.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none /usr/bin/qemu -S -M pc -m 214 -smp 1 -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -vnc unix:/tmp/foo.socket diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-socket.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-socket.xml new file mode 100644 index 0000000000..d6ad72b8a4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-vnc-socket.xml @@ -0,0 +1,30 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219200 + 219200 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 9f74777f50..a7270ecc42 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -321,6 +321,7 @@ mymain(int argc, char **argv) DO_TEST("disk-scsi-device-auto", QEMUD_CMD_FLAG_DRIVE | QEMUD_CMD_FLAG_DEVICE | QEMUD_CMD_FLAG_NODEFCONFIG, false); DO_TEST("graphics-vnc", 0, false); + DO_TEST("graphics-vnc-socket", 0, false); driver.vncSASL = 1; driver.vncSASLdir = strdup("/root/.sasl2");