On Sat, Nov 10, 2012 at 02:40:23 +0100, Alon Levy wrote:
The check for a single display remains so no new functionality is
added.
---
v2 changes:
removed enum, use virReportOOMError directly.
use --patience
added a one line label fix patch.
The second patch changes a string that needs to be translated - how do I go about it?
src/qemu/qemu_command.c | 641 +++++++++++++++++++++++++-----------------------
src/qemu/qemu_process.c | 70 +++---
2 files changed, 364 insertions(+), 347 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1e96982..ba99c7a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4410,6 +4410,331 @@ error:
return -1;
}
+static int
+qemuBuildGraphicsCommandLine(struct qemud_driver *driver,
+ virCommandPtr cmd,
+ virDomainDefPtr def,
+ qemuCapsPtr caps,
+ virDomainGraphicsDefPtr graphics)
+{
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ virBuffer opt = VIR_BUFFER_INITIALIZER;
+
+ if (!qemuCapsGet(caps, QEMU_CAPS_VNC)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("vnc graphics are not supported with this
QEMU"));
+ goto error;
+ }
+
+ if (graphics->data.vnc.socket ||
+ driver->vncAutoUnixSocket) {
+
+ if (!graphics->data.vnc.socket &&
+ virAsprintf(&graphics->data.vnc.socket,
+ "%s/%s.vnc", driver->libDir, def->name) ==
-1) {
+ goto no_memory;
+ }
+
+ virBufferAsprintf(&opt, "unix:%s",
+ graphics->data.vnc.socket);
+
+ } else if (qemuCapsGet(caps, QEMU_CAPS_VNC_COLON)) {
+ const char *listenNetwork;
+ const char *listenAddr = NULL;
+ char *netAddr = NULL;
+ bool escapeAddr;
+ int ret;
+
+ switch (virDomainGraphicsListenGetType(graphics, 0)) {
+ case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
+ listenAddr = virDomainGraphicsListenGetAddress(graphics, 0);
+ break;
+
+ case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
+ listenNetwork = virDomainGraphicsListenGetNetwork(graphics, 0);
+ if (!listenNetwork)
+ break;
+ ret = networkGetNetworkAddress(listenNetwork, &netAddr);
+ if (ret <= -2) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("network-based listen not
possible, "
+ "network driver not present"));
+ goto error;
+ }
+ if (ret < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("listen network '%s' had no usable
address"),
+ listenNetwork);
+ goto error;
+ }
+ listenAddr = netAddr;
+ /* store the address we found in the <graphics> element so it
will
+ * show up in status. */
+ if (virDomainGraphicsListenSetAddress(graphics, 0,
+ listenAddr, -1, false) < 0)
+ goto error;
+ break;
+ }
+
+ if (!listenAddr)
+ listenAddr = driver->vncListen;
+
+ escapeAddr = strchr(listenAddr, ':') != NULL;
+ if (escapeAddr)
+ virBufferAsprintf(&opt, "[%s]", listenAddr);
+ else
+ virBufferAdd(&opt, listenAddr, -1);
+ virBufferAsprintf(&opt, ":%d",
+ graphics->data.vnc.port - 5900);
+
+ VIR_FREE(netAddr);
+ } else {
+ virBufferAsprintf(&opt, "%d",
+ graphics->data.vnc.port - 5900);
+ }
+
+ if (qemuCapsGet(caps, QEMU_CAPS_VNC_COLON)) {
+ if (graphics->data.vnc.auth.passwd ||
+ driver->vncPassword)
+ virBufferAddLit(&opt, ",password");
+
+ if (driver->vncTLS) {
+ virBufferAddLit(&opt, ",tls");
+ if (driver->vncTLSx509verify) {
+ virBufferAsprintf(&opt, ",x509verify=%s",
+ driver->vncTLSx509certdir);
+ } else {
+ virBufferAsprintf(&opt, ",x509=%s",
+ driver->vncTLSx509certdir);
+ }
+ }
+
+ if (driver->vncSASL) {
+ virBufferAddLit(&opt, ",sasl");
+
+ if (driver->vncSASLdir)
+ virCommandAddEnvPair(cmd, "SASL_CONF_DIR",
+ driver->vncSASLdir);
+
+ /* TODO: Support ACLs later */
+ }
+ }
+
+ virCommandAddArg(cmd, "-vnc");
+ virCommandAddArgBuffer(cmd, &opt);
+ if (graphics->data.vnc.keymap) {
+ virCommandAddArgList(cmd, "-k", graphics->data.vnc.keymap,
+ NULL);
+ }
+
+ /* Unless user requested it, set the audio backend to none, to
+ * prevent it opening the host OS audio devices, since that causes
+ * security issues and might not work when using VNC.
+ */
+ if (driver->vncAllowHostAudio) {
+ virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
+ } else {
+ virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
+ }
+ } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+ if (qemuCapsGet(caps, QEMU_CAPS_0_10) &&
+ !qemuCapsGet(caps, QEMU_CAPS_SDL)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("sdl not supported by '%s'"),
+ def->emulator);
+ goto error;
+ }
+
+ if (graphics->data.sdl.xauth)
+ virCommandAddEnvPair(cmd, "XAUTHORITY",
+ graphics->data.sdl.xauth);
+ if (graphics->data.sdl.display)
+ virCommandAddEnvPair(cmd, "DISPLAY",
+ graphics->data.sdl.display);
+ if (graphics->data.sdl.fullscreen)
+ virCommandAddArg(cmd, "-full-screen");
+
+ /* If using SDL for video, then we should just let it
+ * use QEMU's host audio drivers, possibly SDL too
+ * User can set these two before starting libvirtd
+ */
+ virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
+ virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
+
+ /* New QEMU has this flag to let us explicitly ask for
+ * SDL graphics. This is better than relying on the
+ * default, since the default changes :-( */
+ if (qemuCapsGet(caps, QEMU_CAPS_SDL))
+ virCommandAddArg(cmd, "-sdl");
+
+ } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ virBuffer opt = VIR_BUFFER_INITIALIZER;
+ const char *listenNetwork;
+ const char *listenAddr = NULL;
+ char *netAddr = NULL;
+ int ret;
+ int defaultMode = graphics->data.spice.defaultMode;
+
+ if (!qemuCapsGet(caps, QEMU_CAPS_SPICE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("spice graphics are not supported with this
QEMU"));
+ goto error;
+ }
+
+ virBufferAsprintf(&opt, "port=%u", graphics->data.spice.port);
+
+ if (graphics->data.spice.tlsPort > 0) {
+ if (!driver->spiceTLS) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("spice TLS port set in XML configuration,"
+ " but TLS is disabled in qemu.conf"));
+ return 1;
This should be goto error;
+ }
+ virBufferAsprintf(&opt, ",tls-port=%u",
+ graphics->data.spice.tlsPort);
+ }
+
+ switch (virDomainGraphicsListenGetType(graphics, 0)) {
+ case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
+ listenAddr = virDomainGraphicsListenGetAddress(graphics, 0);
+ break;
+
+ case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
+ listenNetwork = virDomainGraphicsListenGetNetwork(graphics, 0);
+ if (!listenNetwork)
+ break;
+ ret = networkGetNetworkAddress(listenNetwork, &netAddr);
+ if (ret <= -2) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("network-based listen not
possible, "
+ "network driver not present"));
+ goto error;
+ }
+ if (ret < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("listen network '%s' had no usable
address"),
+ listenNetwork);
+ goto error;
+ }
+ listenAddr = netAddr;
+ /* store the address we found in the <graphics> element so it will
+ * show up in status. */
+ if (virDomainGraphicsListenSetAddress(graphics, 0,
+ listenAddr, -1, false) < 0)
+ goto error;
+ break;
+ }
+
+ if (!listenAddr)
+ listenAddr = driver->spiceListen;
+ if (listenAddr)
+ virBufferAsprintf(&opt, ",addr=%s", listenAddr);
+
+ VIR_FREE(netAddr);
+
+ int mm = graphics->data.spice.mousemode;
+ if (mm) {
+ switch (mm) {
+ case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
+ virBufferAsprintf(&opt, ",agent-mouse=off");
+ break;
+ case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
+ virBufferAsprintf(&opt, ",agent-mouse=on");
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* In the password case we set it via monitor command, to avoid
+ * making it visible on CLI, so there's no use of password=XXX
+ * in this bit of the code */
+ if (!graphics->data.spice.auth.passwd &&
+ !driver->spicePassword)
+ virBufferAddLit(&opt, ",disable-ticketing");
+
+ if (driver->spiceTLS)
+ virBufferAsprintf(&opt, ",x509-dir=%s",
+ driver->spiceTLSx509certdir);
+
+ switch (defaultMode) {
+ case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
+ virBufferAsprintf(&opt, ",tls-channel=default");
+ break;
+ case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
+ virBufferAsprintf(&opt, ",plaintext-channel=default");
+ break;
+ case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
+ /* nothing */
+ break;
+ }
+
+ for (int i = 0 ; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST ; i++) {
+ int mode = graphics->data.spice.channels[i];
+ switch (mode) {
+ case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
+ if (!driver->spiceTLS) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("spice secure channels set in XML
configuration, but TLS is disabled in qemu.conf"));
+ return 1;
goto error;
+ }
+ virBufferAsprintf(&opt, ",tls-channel=%s",
+ virDomainGraphicsSpiceChannelNameTypeToString(i));
+ break;
+ case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
+ virBufferAsprintf(&opt, ",plaintext-channel=%s",
+ virDomainGraphicsSpiceChannelNameTypeToString(i));
+ break;
+ }
+ }
+ if (graphics->data.spice.image)
+ virBufferAsprintf(&opt, ",image-compression=%s",
+
virDomainGraphicsSpiceImageCompressionTypeToString(graphics->data.spice.image));
+ if (graphics->data.spice.jpeg)
+ virBufferAsprintf(&opt, ",jpeg-wan-compression=%s",
+
virDomainGraphicsSpiceJpegCompressionTypeToString(graphics->data.spice.jpeg));
+ if (graphics->data.spice.zlib)
+ virBufferAsprintf(&opt, ",zlib-glz-wan-compression=%s",
+
virDomainGraphicsSpiceZlibCompressionTypeToString(graphics->data.spice.zlib));
+ if (graphics->data.spice.playback)
+ virBufferAsprintf(&opt, ",playback-compression=%s",
+
virDomainGraphicsSpicePlaybackCompressionTypeToString(graphics->data.spice.playback));
+ if (graphics->data.spice.streaming)
+ virBufferAsprintf(&opt, ",streaming-video=%s",
+
virDomainGraphicsSpiceStreamingModeTypeToString(graphics->data.spice.streaming));
+ if (graphics->data.spice.copypaste ==
VIR_DOMAIN_GRAPHICS_SPICE_CLIPBOARD_COPYPASTE_NO)
+ virBufferAddLit(&opt, ",disable-copy-paste");
+
+ if (qemuCapsGet(caps, QEMU_CAPS_SEAMLESS_MIGRATION)) {
+ /* If qemu supports seamless migration turn it
+ * unconditionally on. If migration destination
+ * doesn't support it, it fallbacks to previous
+ * migration algorithm silently. */
+ virBufferAddLit(&opt, ",seamless-migration=on");
+ }
+
+ virCommandAddArg(cmd, "-spice");
+ virCommandAddArgBuffer(cmd, &opt);
+ if (graphics->data.spice.keymap)
+ virCommandAddArgList(cmd, "-k",
+ graphics->data.spice.keymap, NULL);
+ /* SPICE includes native support for tunnelling audio, so we
+ * set the audio backend to point at SPICE's own driver
+ */
+ virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=spice");
+
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported graphics type '%s'"),
+ virDomainGraphicsTypeToString(graphics->type));
+ goto error;
+ }
+no_memory:
+ virReportOOMError();
+error:
+ return 0;
+}
+
The end of this function is wrong, it would always report no memory and return
success. The following is how it should like:
return 0;
no_memory:
virReportOOMError();
error:
return -1;
Alternatively, all ``goto error'' statements could be replaced with
``return -1'' but this way minimizes modifications to the code being moved so
I'm fine with it as-is.
/*
* Constructs a argv suitable for launching qemu with config defined
* for a given virtual machine.
@@ -5863,322 +6188,12 @@ qemuBuildCommandLine(virConnectPtr conn,
goto error;
}
- if ((def->ngraphics == 1) &&
- def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
- virBuffer opt = VIR_BUFFER_INITIALIZER;
-
- if (!qemuCapsGet(caps, QEMU_CAPS_VNC)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("vnc graphics are not supported with this
QEMU"));
+ for (i = 0 ; i < def->ngraphics ; ++i) {
+ if (qemuBuildGraphicsCommandLine(driver, cmd, def, caps,
+ def->graphics[i]) == -1) {
"def->graphics[i]" should be aligned with "driver" above.
goto error;
}
-
- if (def->graphics[0]->data.vnc.socket ||
- driver->vncAutoUnixSocket) {
-
- if (!def->graphics[0]->data.vnc.socket &&
- virAsprintf(&def->graphics[0]->data.vnc.socket,
- "%s/%s.vnc", driver->libDir, def->name) ==
-1) {
- goto no_memory;
- }
-
- virBufferAsprintf(&opt, "unix:%s",
- def->graphics[0]->data.vnc.socket);
-
- } else if (qemuCapsGet(caps, QEMU_CAPS_VNC_COLON)) {
- const char *listenNetwork;
- const char *listenAddr = NULL;
- char *netAddr = NULL;
- bool escapeAddr;
- int ret;
-
- switch (virDomainGraphicsListenGetType(def->graphics[0], 0)) {
- case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
- listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0);
- break;
-
- case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
- listenNetwork = virDomainGraphicsListenGetNetwork(def->graphics[0],
0);
- if (!listenNetwork)
- break;
- ret = networkGetNetworkAddress(listenNetwork, &netAddr);
- if (ret <= -2) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("network-based listen not
possible, "
- "network driver not present"));
- goto error;
- }
- if (ret < 0) {
- virReportError(VIR_ERR_XML_ERROR,
- _("listen network '%s' had no usable
address"),
- listenNetwork);
- goto error;
- }
- listenAddr = netAddr;
- /* store the address we found in the <graphics> element so it
will
- * show up in status. */
- if (virDomainGraphicsListenSetAddress(def->graphics[0], 0,
- listenAddr, -1, false) < 0)
- goto error;
- break;
- }
-
- if (!listenAddr)
- listenAddr = driver->vncListen;
-
- escapeAddr = strchr(listenAddr, ':') != NULL;
- if (escapeAddr)
- virBufferAsprintf(&opt, "[%s]", listenAddr);
- else
- virBufferAdd(&opt, listenAddr, -1);
- virBufferAsprintf(&opt, ":%d",
- def->graphics[0]->data.vnc.port - 5900);
-
- VIR_FREE(netAddr);
- } else {
- virBufferAsprintf(&opt, "%d",
- def->graphics[0]->data.vnc.port - 5900);
- }
-
- if (qemuCapsGet(caps, QEMU_CAPS_VNC_COLON)) {
- if (def->graphics[0]->data.vnc.auth.passwd ||
- driver->vncPassword)
- virBufferAddLit(&opt, ",password");
-
- if (driver->vncTLS) {
- virBufferAddLit(&opt, ",tls");
- if (driver->vncTLSx509verify) {
- virBufferAsprintf(&opt, ",x509verify=%s",
- driver->vncTLSx509certdir);
- } else {
- virBufferAsprintf(&opt, ",x509=%s",
- driver->vncTLSx509certdir);
- }
- }
-
- if (driver->vncSASL) {
- virBufferAddLit(&opt, ",sasl");
-
- if (driver->vncSASLdir)
- virCommandAddEnvPair(cmd, "SASL_CONF_DIR",
- driver->vncSASLdir);
-
- /* TODO: Support ACLs later */
- }
- }
-
- virCommandAddArg(cmd, "-vnc");
- virCommandAddArgBuffer(cmd, &opt);
- if (def->graphics[0]->data.vnc.keymap) {
- virCommandAddArgList(cmd, "-k",
def->graphics[0]->data.vnc.keymap,
- NULL);
- }
-
- /* Unless user requested it, set the audio backend to none, to
- * prevent it opening the host OS audio devices, since that causes
- * security issues and might not work when using VNC.
- */
- if (driver->vncAllowHostAudio) {
- virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
- } else {
- virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
- }
- } else if ((def->ngraphics == 1) &&
- def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
- if (qemuCapsGet(caps, QEMU_CAPS_0_10) &&
- !qemuCapsGet(caps, QEMU_CAPS_SDL)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("sdl not supported by '%s'"),
- def->emulator);
- goto error;
- }
-
- if (def->graphics[0]->data.sdl.xauth)
- virCommandAddEnvPair(cmd, "XAUTHORITY",
- def->graphics[0]->data.sdl.xauth);
- if (def->graphics[0]->data.sdl.display)
- virCommandAddEnvPair(cmd, "DISPLAY",
- def->graphics[0]->data.sdl.display);
- if (def->graphics[0]->data.sdl.fullscreen)
- virCommandAddArg(cmd, "-full-screen");
-
- /* If using SDL for video, then we should just let it
- * use QEMU's host audio drivers, possibly SDL too
- * User can set these two before starting libvirtd
- */
- virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
- virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
-
- /* New QEMU has this flag to let us explicitly ask for
- * SDL graphics. This is better than relying on the
- * default, since the default changes :-( */
- if (qemuCapsGet(caps, QEMU_CAPS_SDL))
- virCommandAddArg(cmd, "-sdl");
-
- } else if ((def->ngraphics == 1) &&
- def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
- virBuffer opt = VIR_BUFFER_INITIALIZER;
- const char *listenNetwork;
- const char *listenAddr = NULL;
- char *netAddr = NULL;
- int ret;
- int defaultMode = def->graphics[0]->data.spice.defaultMode;
-
- if (!qemuCapsGet(caps, QEMU_CAPS_SPICE)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("spice graphics are not supported with this
QEMU"));
- goto error;
- }
-
- virBufferAsprintf(&opt, "port=%u",
def->graphics[0]->data.spice.port);
-
- if (def->graphics[0]->data.spice.tlsPort > 0) {
- if (!driver->spiceTLS) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("spice TLS port set in XML configuration,"
- " but TLS is disabled in qemu.conf"));
- goto error;
- }
- virBufferAsprintf(&opt, ",tls-port=%u",
- def->graphics[0]->data.spice.tlsPort);
- }
-
- switch (virDomainGraphicsListenGetType(def->graphics[0], 0)) {
- case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
- listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0);
- break;
-
- case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
- listenNetwork = virDomainGraphicsListenGetNetwork(def->graphics[0], 0);
- if (!listenNetwork)
- break;
- ret = networkGetNetworkAddress(listenNetwork, &netAddr);
- if (ret <= -2) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("network-based listen not
possible, "
- "network driver not present"));
- goto error;
- }
- if (ret < 0) {
- virReportError(VIR_ERR_XML_ERROR,
- _("listen network '%s' had no usable
address"),
- listenNetwork);
- goto error;
- }
- listenAddr = netAddr;
- /* store the address we found in the <graphics> element so it will
- * show up in status. */
- if (virDomainGraphicsListenSetAddress(def->graphics[0], 0,
- listenAddr, -1, false) < 0)
- goto error;
- break;
- }
-
- if (!listenAddr)
- listenAddr = driver->spiceListen;
- if (listenAddr)
- virBufferAsprintf(&opt, ",addr=%s", listenAddr);
-
- VIR_FREE(netAddr);
-
- int mm = def->graphics[0]->data.spice.mousemode;
- if (mm) {
- switch (mm) {
- case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
- virBufferAsprintf(&opt, ",agent-mouse=off");
- break;
- case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
- virBufferAsprintf(&opt, ",agent-mouse=on");
- break;
- default:
- break;
- }
- }
-
- /* In the password case we set it via monitor command, to avoid
- * making it visible on CLI, so there's no use of password=XXX
- * in this bit of the code */
- if (!def->graphics[0]->data.spice.auth.passwd &&
- !driver->spicePassword)
- virBufferAddLit(&opt, ",disable-ticketing");
-
- if (driver->spiceTLS)
- virBufferAsprintf(&opt, ",x509-dir=%s",
- driver->spiceTLSx509certdir);
-
- switch (defaultMode) {
- case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
- virBufferAsprintf(&opt, ",tls-channel=default");
- break;
- case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
- virBufferAsprintf(&opt, ",plaintext-channel=default");
- break;
- case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY:
- /* nothing */
- break;
- }
-
- for (i = 0 ; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST ; i++) {
- int mode = def->graphics[0]->data.spice.channels[i];
- switch (mode) {
- case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE:
- if (!driver->spiceTLS) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("spice secure channels set in XML
configuration, but TLS is disabled in qemu.conf"));
- goto error;
- }
- virBufferAsprintf(&opt, ",tls-channel=%s",
- virDomainGraphicsSpiceChannelNameTypeToString(i));
- break;
- case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE:
- virBufferAsprintf(&opt, ",plaintext-channel=%s",
- virDomainGraphicsSpiceChannelNameTypeToString(i));
- break;
- }
- }
- if (def->graphics[0]->data.spice.image)
- virBufferAsprintf(&opt, ",image-compression=%s",
-
virDomainGraphicsSpiceImageCompressionTypeToString(def->graphics[0]->data.spice.image));
- if (def->graphics[0]->data.spice.jpeg)
- virBufferAsprintf(&opt, ",jpeg-wan-compression=%s",
-
virDomainGraphicsSpiceJpegCompressionTypeToString(def->graphics[0]->data.spice.jpeg));
- if (def->graphics[0]->data.spice.zlib)
- virBufferAsprintf(&opt, ",zlib-glz-wan-compression=%s",
-
virDomainGraphicsSpiceZlibCompressionTypeToString(def->graphics[0]->data.spice.zlib));
- if (def->graphics[0]->data.spice.playback)
- virBufferAsprintf(&opt, ",playback-compression=%s",
-
virDomainGraphicsSpicePlaybackCompressionTypeToString(def->graphics[0]->data.spice.playback));
- if (def->graphics[0]->data.spice.streaming)
- virBufferAsprintf(&opt, ",streaming-video=%s",
-
virDomainGraphicsSpiceStreamingModeTypeToString(def->graphics[0]->data.spice.streaming));
- if (def->graphics[0]->data.spice.copypaste ==
VIR_DOMAIN_GRAPHICS_SPICE_CLIPBOARD_COPYPASTE_NO)
- virBufferAddLit(&opt, ",disable-copy-paste");
-
- if (qemuCapsGet(caps, QEMU_CAPS_SEAMLESS_MIGRATION)) {
- /* If qemu supports seamless migration turn it
- * unconditionally on. If migration destination
- * doesn't support it, it fallbacks to previous
- * migration algorithm silently. */
- virBufferAddLit(&opt, ",seamless-migration=on");
- }
-
- virCommandAddArg(cmd, "-spice");
- virCommandAddArgBuffer(cmd, &opt);
- if (def->graphics[0]->data.spice.keymap)
- virCommandAddArgList(cmd, "-k",
- def->graphics[0]->data.spice.keymap, NULL);
- /* SPICE includes native support for tunnelling audio, so we
- * set the audio backend to point at SPICE's own driver
- */
- virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=spice");
-
- } else if ((def->ngraphics == 1)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("unsupported graphics type '%s'"),
- virDomainGraphicsTypeToString(def->graphics[0]->type));
- goto error;
}
-
if (def->nvideos > 0) {
if (qemuCapsGet(caps, QEMU_CAPS_VGA)) {
if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_XEN) {
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d8cf4c3..2a77290 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2081,16 +2081,17 @@ qemuProcessInitPasswords(virConnectPtr conn,
int ret = 0;
qemuDomainObjPrivatePtr priv = vm->privateData;
- if (vm->def->ngraphics == 1) {
- if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ for (int i = 0 ; i < vm->def->ngraphics; ++i) {
+ virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
ret = qemuDomainChangeGraphicsPasswords(driver, vm,
VIR_DOMAIN_GRAPHICS_TYPE_VNC,
-
&vm->def->graphics[0]->data.vnc.auth,
+ &graphics->data.vnc.auth,
driver->vncPassword);
- } else if (vm->def->graphics[0]->type ==
VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
ret = qemuDomainChangeGraphicsPasswords(driver, vm,
VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
-
&vm->def->graphics[0]->data.spice.auth,
+ &graphics->data.spice.auth,
driver->spicePassword);
}
}
@@ -3484,21 +3485,22 @@ int qemuProcessStart(virConnectPtr conn,
VIR_DEBUG("Ensuring no historical cgroup is lying around");
qemuRemoveCgroup(driver, vm, 1);
- 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) {
+ for (i = 0 ; i < vm->def->ngraphics; ++i) {
+ virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ !graphics->data.vnc.socket &&
+ graphics->data.vnc.autoport) {
int port = qemuProcessNextFreePort(driver, driver->remotePortMin);
if (port < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to find an unused port for
VNC"));
goto cleanup;
}
- vm->def->graphics[0]->data.vnc.port = port;
- } else if (vm->def->graphics[0]->type ==
VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
+ graphics->data.vnc.port = port;
+ } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
int port = -1;
- if (vm->def->graphics[0]->data.spice.autoport ||
- vm->def->graphics[0]->data.spice.port == -1) {
+ if (graphics->data.spice.autoport ||
+ graphics->data.spice.port == -1) {
port = qemuProcessNextFreePort(driver, driver->remotePortMin);
if (port < 0) {
@@ -3507,13 +3509,13 @@ int qemuProcessStart(virConnectPtr conn,
goto cleanup;
}
- vm->def->graphics[0]->data.spice.port = port;
+ graphics->data.spice.port = port;
}
if (driver->spiceTLS &&
- (vm->def->graphics[0]->data.spice.autoport ||
- vm->def->graphics[0]->data.spice.tlsPort == -1)) {
+ (graphics->data.spice.autoport ||
+ graphics->data.spice.tlsPort == -1)) {
int tlsPort = qemuProcessNextFreePort(driver,
-
vm->def->graphics[0]->data.spice.port + 1);
+ graphics->data.spice.port +
1);
if (tlsPort < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to find an unused port
for SPICE TLS"));
@@ -3521,20 +3523,19 @@ int qemuProcessStart(virConnectPtr conn,
goto cleanup;
}
- vm->def->graphics[0]->data.spice.tlsPort = tlsPort;
+ graphics->data.spice.tlsPort = tlsPort;
}
}
- if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC ||
- vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
- virDomainGraphicsDefPtr graphics = vm->def->graphics[0];
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC ||
+ graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
if (graphics->nListens == 0) {
if (VIR_EXPAND_N(graphics->listens, graphics->nListens, 1) < 0)
{
virReportOOMError();
goto cleanup;
}
graphics->listens[0].type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
- if (vm->def->graphics[0]->type ==
VIR_DOMAIN_GRAPHICS_TYPE_VNC)
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC)
graphics->listens[0].address = strdup(driver->vncListen);
else
graphics->listens[0].address = strdup(driver->spiceListen);
@@ -4150,19 +4151,20 @@ retry:
qemuProcessRemoveDomainStatus(driver, vm);
- /* Remove VNC port from port reservation bitmap, but only if it was
- reserved by the driver (autoport=yes)
+ /* Remove VNC and Spice ports from port reservation bitmap, but only if
+ they were reserved by the driver (autoport=yes)
*/
- if ((vm->def->ngraphics == 1) &&
- vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
- vm->def->graphics[0]->data.vnc.autoport) {
- qemuProcessReturnPort(driver, vm->def->graphics[0]->data.vnc.port);
- }
- if ((vm->def->ngraphics == 1) &&
- vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE
&&
- vm->def->graphics[0]->data.spice.autoport) {
- qemuProcessReturnPort(driver, vm->def->graphics[0]->data.spice.port);
- qemuProcessReturnPort(driver,
vm->def->graphics[0]->data.spice.tlsPort);
+ for (i = 0 ; i < vm->def->ngraphics; ++i) {
+ virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ graphics->data.vnc.autoport) {
+ qemuProcessReturnPort(driver, graphics->data.vnc.port);
+ }
+ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
+ graphics->data.spice.autoport) {
+ qemuProcessReturnPort(driver, graphics->data.spice.port);
+ qemuProcessReturnPort(driver, graphics->data.spice.tlsPort);
+ }
}
vm->taint = 0;
I'd prefer if the refactoring of qemuBuildCommandLine was separated from
removing the limit for number of graphics cards. But since I already reviewed
the patch and I don't want to do that again, I'm giving a formal ACK to this
version (with the small issues fixed, of course).
Since you don't have commit rights, I'll fix the issues and push the patches.
Jirka