SPICE 和 virt-manager 不支持自动调整大小

SPICE 和 virt-manager 不支持自动调整大小

我设置了一个虚拟机,除了自动调整大小功能似乎不一致之外,它运行良好。我让它随机工作了几次,但它也随机停止工作。它目前不工作,我不确定我需要做什么才能让它可靠地工作(比如 VirtualBox 自动调整大小)。请参阅下面的配置。

设置

Host: Ubuntu 16.10
Guest: Ubuntu 16.04.2, et. al (I've tried with other Linux distros with similar results)
Guest: created using virt-manager
Guest: installed spice-vdagent
Guest: virt-manager > View > Scale Display > Auto resize VM with window (checked)

香料

user@ubuntu:~$ ps aux | grep spice
root       805  0.0  0.0  30568   260 ?        Ss   08:59   0:00 /usr/sbin/spice-vdagentd
user      1365  0.0  0.0  35124  2360 ?        Ss   08:59   0:00 /usr/bin/spice-vdagent
user      1933  0.0  0.0  21292  1020 pts/17   S+   09:00   0:00 grep --color=auto spice

青霞

user@ubuntu:~$ sudo lshw -c Video
  *-display               
       description: VGA compatible controller
       product: QXL paravirtual graphic card
       vendor: Red Hat, Inc.
       physical id: 2
       bus info: pci@0000:00:02.0
       version: 04
       width: 32 bits
       clock: 33MHz
       capabilities: vga_controller rom
       configuration: driver=qxl latency=0
       resources: irq:10 memory:f4000000-f7ffffff memory:f8000000-fbffffff memory:fc058000-fc059fff ioport:c040(size=32) memory:c0000-dffff

我缺少什么来正确启用 qemu/kvm 的自动调整大小?

答案1

gnome 桌面,mutter,有一些处理调整大小的热插拔代码。

如果您有任何其他桌面,例如 xfce4 或 KDE,或者像我一样运行 compiz 的裸 .xinitrc 文件,那么您会遇到很多困难,但我想我终于找到了一个优雅而简单的解决方案。

xrandr --output Virtual-0 --auto 将从 vdagent 中获取大小并应用。所需的只是一个触发器。

这是触发器以及处理它的方法。

udev将调整大小事件公开为如下所示的drm设备:change
UDEV [10758.537471] change /devices/pci0000:00/0000:00:02.0 `drm/card0 (drm)

要让您的桌面对其做出反应,请创建一个udev规则并引用脚本来调整大小:
规则/etc/udev/rules.d/50-x-resize.rules

ACTION=="change",KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/usr/local/bin/x-resize" 

/usr/local/bin/x-resize 中的脚本:

#! /bin/sh
PATH=/usr/bin
export DISPLAY=:0.0
xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto

您可能需要根据您的情况定制该 shell 脚本。

我发现在 debian 10 和 Ubuntu 20.04 上我甚至不需要重新启动任何东西;它会立即恢复。

更新:2021-03-17

我最近发现我必须获得权限才能允许该脚本运行。我将其更改为:

#! /bin/sh 
PATH=/usr/bin
desktopuser=$(/bin/ps -ef  | /bin/grep -oP '^\w+ (?=.*vdagent( |$))') || exit 0
export DISPLAY=:0
export XAUTHORITY=$(eval echo "~$desktopuser")/.Xauthority
xrandr --output $(xrandr | awk '/ connected/{print $1; exit; }') --auto

答案2

我使用 Debian 10 和 icewm 作为客户虚拟机。当 spice-vdagent 运行时,我可以使用以下命令手动调整屏幕尺寸xrandr --output Virtual-1 --auto

使用 xev 也可以观察到显示尺寸的变化:

joe@l1:~$ xev -root -event randr 

RRScreenChangeNotify event, serial 18, synthetic NO, window 0x3af,
    root 0x3af, timestamp 39153, config_timestamp 82137
    size_index 65535, subpixel_order SubPixelUnknown
    rotation RR_Rotate_0
    width 1320, height 949, mwidth 348, mheight 250

RRNotify event, serial 18, synthetic NO, window 0x3af,
    subtype XRROutputChangeNotifyEvent
    output Virtual-1, crtc 63, mode 1320x949 (1320x949)
    rotation RR_Rotate_0
    connection RR_Connected, subpixel_order SubPixelUnknown

使用它作为触发器似乎比使用 udev 更少干扰,特别是在同一个 VM 中使用不同的桌面环境或窗口管理器时。

joe@l1:~$ cat /home/joe/.xsession
#!/bin/sh

if [ -x /usr/bin/spice-vdagent ] ; then
    /usr/bin/spice-vdagent
    /home/joe/.icewm/xrandr-loop &
fi
exec /usr/bin/icewm-session

joe@l1:~$ cat /home/joe/.icewm/xrandr-loop
#!/bin/sh

sleep 2

xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto

xev -root -event randr | \
grep --line-buffered 'subtype XRROutputChangeNotifyEvent' | \
while read foo ; do \
    xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto
done

joe@l1:~$ 

答案3

我很难让我的客户虚拟机支持分辨率大于 1080p 的两个显示器。事实证明,这是因为默认的 QXL 内存缓冲区 16 mib 不够大。如果您的两个显示器都只有 1080p,您可能不会遇到此问题。但如果是,则需要heads=2通过属性设置并增加内存缓冲区vgamem(在我的情况下,32 mib 有效)。

在我的系统上,我必须手动编辑 libvirt XML 配置才能进行此更改。为此,请查找属性vgamem。它可能具有默认值16384(即 16 mib)。要增加它,例如 32 mib,请将属性值更改为32768。在我的系统上,以下修改后的 XML 片段来自:

<video>
  <model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
  <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>

到:

<video>
  <model type="qxl" ram="65536" vram="65536" vgamem="32768" heads="2" primary="yes"/>
  <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>

如果您不确定实际使用的值,您可以通过查看qemu命令行参数来找出答案。在 Unix/Linux 系统上,启动客户机,然后运行ps -ef | grep qemu​​... 并查找 QXL 设备。它可能看起来像-device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=32,max_outputs=2,bus=pcie.0,addr=0x1vgamem_mb的价值三十二才是最重要的。

正确设置 QXL 驱动程序后,更改客户机分辨率应该很容易。您可以使用图形显示配置器,也可以xrandr通过命令行使用。就我而言,我选择使用以下脚本自动执行该过程:

#!/bin/bash
if [ `xrandr | grep --extended-regexp --count "Virtual-0 connected|Virtual-1 connected"` == 2 ]; then
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode Virtual-0 "1920x1200_60.00"
xrandr --addmode Virtual-1 "1920x1200_60.00"
xrandr --output Virtual-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0 --output Virtual-1 --mode "1920x1200_60.00" --panning 1920x1200+1920+0
elif [ `xrandr | grep --extended-regexp --count "qxl-0 connected|qxl-1 connected"` == 2 ]; then
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode qxl-0 "1920x1200_60.00"
xrandr --addmode qxl-1 "1920x1200_60.00"
xrandr --output qxl-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0 --output qxl-1 --mode "1920x1200_60.00" --panning 1920x1200+1920+0
elif [ `xrandr | grep --extended-regexp --count "Virtual-0 connected"` == 1 ]; then
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode Virtual-0 "1920x1200_60.00"
xrandr --output Virtual-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0
else
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode qxl-0 "1920x1200_60.00"
xrandr --output qxl-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0
fi

请注意,这是针对 1920x1200 的设置。还值得注意的是,根据您的显示服务器、内核版本和驱动程序设置等,显示适配器可能会显示为“qxl-#”或“Virtual-#”。

要将上述脚本用于 1920x1200 以外的分辨率,您需要使用适当的模式行。要获取正确的模式行,请使用cvt命令行工具。例如,如果您想要的是 4k(又称 2160p)显示器的模式行,您可以运行cvt 3840 2160 60(假设刷新率为 60hz)。这将为您提供模式行:

# 3840x2160 59.98 Hz (CVT 8.29M9) hsync: 134.18 kHz; pclk: 712.75 MHz
Modeline "3840x2160_60.00"  712.75  3840 4160 4576 5312  2160 2163 2168 2237 -hsync +vsync

现在获取“Modeline”之后显示的值:

"3840x2160_60.00"  712.75  3840 4160 4576 5312  2160 2163 2168 2237 -hsync +vsync

并替换值:

"1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync

在上面的示例脚本中。

几点说明。也就是说,引号内的文本实际上是“标签”...因此您需要将引用替换为"1920x1200_60.00"新模式行的标签。还值得注意的是,您可以在调用时省略刷新率cvt,它会猜测...但如果您在客户系统内运行它,那么猜测可能会出错。为避免此问题,您可能需要在主机上调用cvt。在这种情况下,您可以省略刷新率,并cvt通过查看硬件来确定正确的值。

答案4

如果您使用的桌面环境(例如 Xfce)本身不支持动态屏幕调整大小(https://gitlab.xfce.org/xfce/xfce4-settings/-/issues/142),您可以运行一个脚本,该脚本xrandr -s 0在 udev 每次通知drm子系统发生变化时调用,以实现类似的功能。

对于易于打包/安装的易于使用的解决方案,您可能有兴趣尝试以下操作:https://gitlab.com/Apteryks/x-resize/,它将安装一个自动启动脚本并记录屏幕变化~/.local/state/x-resize.log.1

2023-12-30 04:31:58 (INFO): x-resize started; logging to /home/guest/.local/state/x-resize.log
2023-12-30 04:33:41 (INFO): screen 0 resized from 1024x768 to 1918x1010
2023-12-30 04:33:48 (INFO): screen 0 resized from 1918x1010 to 958x1010
2023-12-30 04:34:27 (INFO): screen 0 resized from 958x1010 to 958x470

它在 GNU Guix 中可用,可以通过 进行安装guix install x-resize

相关内容