mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
bhyve: add video support
bhyve supports 'gop' video device that allows clients to connect to VMs using VNC clients. This commit adds support for that to the bhyve driver: - Introducr 'gop' video device type - Add capabilities probing for the 'fbuf' device that's responsible for graphics - Update command builder routines to let users configure domain's VNC via gop graphics. Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
This commit is contained in:
parent
58b49d0c19
commit
04664327c6
@ -5891,8 +5891,9 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
<p>
|
<p>
|
||||||
The <code>model</code> element has a mandatory <code>type</code>
|
The <code>model</code> element has a mandatory <code>type</code>
|
||||||
attribute which takes the value "vga", "cirrus", "vmvga", "xen",
|
attribute which takes the value "vga", "cirrus", "vmvga", "xen",
|
||||||
"vbox", "qxl" (<span class="since">since 0.8.6</span>) or
|
"vbox", "qxl" (<span class="since">since 0.8.6</span>),
|
||||||
"virtio" (<span class="since">since 1.3.0</span>)
|
"virtio" (<span class="since">since 1.3.0</span>)
|
||||||
|
or "gop" (<span class="since">since 3.2.0</span>)
|
||||||
depending on the hypervisor features available.
|
depending on the hypervisor features available.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -3166,6 +3166,7 @@
|
|||||||
<value>xen</value>
|
<value>xen</value>
|
||||||
<value>vbox</value>
|
<value>vbox</value>
|
||||||
<value>virtio</value>
|
<value>virtio</value>
|
||||||
|
<value>gop</value>
|
||||||
</choice>
|
</choice>
|
||||||
</attribute>
|
</attribute>
|
||||||
<group>
|
<group>
|
||||||
|
@ -12,6 +12,7 @@ gnulib/lib/getopt.c
|
|||||||
gnulib/lib/regcomp.c
|
gnulib/lib/regcomp.c
|
||||||
src/access/viraccessdriverpolkit.c
|
src/access/viraccessdriverpolkit.c
|
||||||
src/access/viraccessmanager.c
|
src/access/viraccessmanager.c
|
||||||
|
src/bhyve/bhyve_capabilities.c
|
||||||
src/bhyve/bhyve_command.c
|
src/bhyve/bhyve_command.c
|
||||||
src/bhyve/bhyve_device.c
|
src/bhyve/bhyve_device.c
|
||||||
src/bhyve/bhyve_domain.c
|
src/bhyve/bhyve_domain.c
|
||||||
|
@ -117,6 +117,7 @@ virBhyveDomainCapsBuild(const char *emulatorbin,
|
|||||||
virDomainVirtType virttype)
|
virDomainVirtType virttype)
|
||||||
{
|
{
|
||||||
virDomainCapsPtr caps = NULL;
|
virDomainCapsPtr caps = NULL;
|
||||||
|
unsigned int bhyve_caps = 0;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
const char *firmware_dir = "/usr/local/share/uefi-firmware";
|
const char *firmware_dir = "/usr/local/share/uefi-firmware";
|
||||||
@ -125,6 +126,12 @@ virBhyveDomainCapsBuild(const char *emulatorbin,
|
|||||||
if (!(caps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
|
if (!(caps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virBhyveProbeCaps(&bhyve_caps)) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("failed probing capabilities"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
caps->os.supported = true;
|
caps->os.supported = true;
|
||||||
caps->os.loader.supported = true;
|
caps->os.loader.supported = true;
|
||||||
VIR_DOMAIN_CAPS_ENUM_SET(caps->os.loader.type,
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->os.loader.type,
|
||||||
@ -155,6 +162,12 @@ virBhyveDomainCapsBuild(const char *emulatorbin,
|
|||||||
VIR_DOMAIN_DISK_BUS_SATA,
|
VIR_DOMAIN_DISK_BUS_SATA,
|
||||||
VIR_DOMAIN_DISK_BUS_VIRTIO);
|
VIR_DOMAIN_DISK_BUS_VIRTIO);
|
||||||
|
|
||||||
|
if (bhyve_caps & BHYVE_CAP_FBUF) {
|
||||||
|
caps->graphics.supported = true;
|
||||||
|
caps->video.supported = true;
|
||||||
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->graphics.type, VIR_DOMAIN_GRAPHICS_TYPE_VNC);
|
||||||
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->video.modelType, VIR_DOMAIN_VIDEO_TYPE_GOP);
|
||||||
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_DIR_CLOSE(dir);
|
VIR_DIR_CLOSE(dir);
|
||||||
return caps;
|
return caps;
|
||||||
@ -290,6 +303,30 @@ bhyveProbeCapsLPC_Bootrom(unsigned int *caps, char *binary)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveProbeCapsFramebuffer(unsigned int *caps, char *binary)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
virCommandPtr cmd = NULL;
|
||||||
|
int ret = -1, exit;
|
||||||
|
|
||||||
|
cmd = virCommandNew(binary);
|
||||||
|
virCommandAddArgList(cmd, "-s", "0,fbuf", NULL);
|
||||||
|
virCommandSetErrorBuffer(cmd, &error);
|
||||||
|
if (virCommandRun(cmd, &exit) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (strstr(error, "pci slot 0:0: unknown device \"fbuf\"") == NULL)
|
||||||
|
*caps |= BHYVE_CAP_FBUF;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(error);
|
||||||
|
virCommandFree(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
virBhyveProbeCaps(unsigned int *caps)
|
virBhyveProbeCaps(unsigned int *caps)
|
||||||
{
|
{
|
||||||
@ -314,6 +351,9 @@ virBhyveProbeCaps(unsigned int *caps)
|
|||||||
if ((ret = bhyveProbeCapsLPC_Bootrom(caps, binary)))
|
if ((ret = bhyveProbeCapsLPC_Bootrom(caps, binary)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if ((ret = bhyveProbeCapsFramebuffer(caps, binary)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
VIR_FREE(binary);
|
VIR_FREE(binary);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -41,6 +41,7 @@ typedef enum {
|
|||||||
BHYVE_CAP_AHCI32SLOT = 1 << 1,
|
BHYVE_CAP_AHCI32SLOT = 1 << 1,
|
||||||
BHYVE_CAP_NET_E1000 = 1 << 2,
|
BHYVE_CAP_NET_E1000 = 1 << 2,
|
||||||
BHYVE_CAP_LPC_BOOTROM = 1 << 3,
|
BHYVE_CAP_LPC_BOOTROM = 1 << 3,
|
||||||
|
BHYVE_CAP_FBUF = 1 << 4,
|
||||||
} virBhyveCapsFlags;
|
} virBhyveCapsFlags;
|
||||||
|
|
||||||
int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps);
|
int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps);
|
||||||
|
@ -290,6 +290,94 @@ bhyveBuildLPCArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveBuildGraphicsArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
|
||||||
|
virDomainGraphicsDefPtr graphics,
|
||||||
|
virDomainVideoDefPtr video,
|
||||||
|
virConnectPtr conn,
|
||||||
|
virCommandPtr cmd)
|
||||||
|
{
|
||||||
|
virBuffer opt = VIR_BUFFER_INITIALIZER;
|
||||||
|
virDomainGraphicsListenDefPtr glisten = NULL;
|
||||||
|
bool escapeAddr;
|
||||||
|
|
||||||
|
if (!(bhyveDriverGetCaps(conn) & BHYVE_CAP_LPC_BOOTROM) ||
|
||||||
|
def->os.bootloader ||
|
||||||
|
!def->os.loader) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Graphics are only supported"
|
||||||
|
" when booting using UEFI"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(bhyveDriverGetCaps(conn) & BHYVE_CAP_FBUF)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Bhyve version does not support framebuffer"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Only VNC supported"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(glisten = virDomainGraphicsGetListen(graphics, 0))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Missing listen element"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAsprintf(&opt, "%d:%d,fbuf", video->info.addr.pci.slot, video->info.addr.pci.function);
|
||||||
|
|
||||||
|
switch (glisten->type) {
|
||||||
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
|
||||||
|
case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
|
||||||
|
virBufferAddLit(&opt, ",tcp=");
|
||||||
|
|
||||||
|
if (!graphics->data.vnc.autoport &&
|
||||||
|
(graphics->data.vnc.port < 5900 ||
|
||||||
|
graphics->data.vnc.port > 65535)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("vnc port must be in range [5900,65535]"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphics->data.vnc.auth.passwd) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("vnc password auth not supported"));
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
/* Bhyve doesn't support VNC Auth yet, so print a warning about
|
||||||
|
* unauthenticated VNC sessions */
|
||||||
|
VIR_WARN("%s", _("Security warning: currently VNC auth is not"
|
||||||
|
" supported."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glisten->address) {
|
||||||
|
escapeAddr = strchr(glisten->address, ':') != NULL;
|
||||||
|
if (escapeAddr)
|
||||||
|
virBufferAsprintf(&opt, "[%s]", glisten->address);
|
||||||
|
else
|
||||||
|
virBufferAdd(&opt, glisten->address, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAsprintf(&opt, ":%d", graphics->data.vnc.port);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Unsupported listen type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "-s");
|
||||||
|
virCommandAddArgBuffer(cmd, &opt);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virBufferFreeAndReset(&opt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
virCommandPtr
|
virCommandPtr
|
||||||
virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
|
virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
|
||||||
virDomainDefPtr def, bool dryRun)
|
virDomainDefPtr def, bool dryRun)
|
||||||
@ -413,6 +501,18 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (def->ngraphics && def->nvideos) {
|
||||||
|
if (def->ngraphics == 1 && def->nvideos == 1) {
|
||||||
|
if (bhyveBuildGraphicsArgStr(def, def->graphics[0], def->videos[0], conn, cmd) < 0)
|
||||||
|
goto error;
|
||||||
|
add_lpc = true;
|
||||||
|
} else {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("Multiple graphics devices are not supported"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (add_lpc || def->nserials)
|
if (add_lpc || def->nserials)
|
||||||
bhyveBuildLPCArgStr(def, cmd);
|
bhyveBuildLPCArgStr(def, cmd);
|
||||||
|
|
||||||
|
@ -145,6 +145,17 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < def->nvideos; i++) {
|
||||||
|
if (!virDeviceInfoPCIAddressWanted(&def->videos[i]->info))
|
||||||
|
continue;
|
||||||
|
if (virDomainPCIAddressReserveNextAddr(addrs,
|
||||||
|
&def->videos[i]->info,
|
||||||
|
VIR_PCI_CONNECT_TYPE_PCI_DEVICE,
|
||||||
|
-1) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -545,7 +545,8 @@ VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
|
|||||||
"vbox",
|
"vbox",
|
||||||
"qxl",
|
"qxl",
|
||||||
"parallels",
|
"parallels",
|
||||||
"virtio")
|
"virtio",
|
||||||
|
"gop")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST,
|
VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST,
|
||||||
"mouse",
|
"mouse",
|
||||||
@ -13049,6 +13050,8 @@ virDomainVideoDefaultType(const virDomainDef *def)
|
|||||||
return VIR_DOMAIN_VIDEO_TYPE_VGA;
|
return VIR_DOMAIN_VIDEO_TYPE_VGA;
|
||||||
else
|
else
|
||||||
return VIR_DOMAIN_VIDEO_TYPE_PARALLELS;
|
return VIR_DOMAIN_VIDEO_TYPE_PARALLELS;
|
||||||
|
case VIR_DOMAIN_VIRT_BHYVE:
|
||||||
|
return VIR_DOMAIN_VIDEO_TYPE_GOP;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1335,6 +1335,7 @@ typedef enum {
|
|||||||
VIR_DOMAIN_VIDEO_TYPE_QXL,
|
VIR_DOMAIN_VIDEO_TYPE_QXL,
|
||||||
VIR_DOMAIN_VIDEO_TYPE_PARALLELS, /* pseudo device for VNC in containers */
|
VIR_DOMAIN_VIDEO_TYPE_PARALLELS, /* pseudo device for VNC in containers */
|
||||||
VIR_DOMAIN_VIDEO_TYPE_VIRTIO,
|
VIR_DOMAIN_VIDEO_TYPE_VIRTIO,
|
||||||
|
VIR_DOMAIN_VIDEO_TYPE_GOP,
|
||||||
|
|
||||||
VIR_DOMAIN_VIDEO_TYPE_LAST
|
VIR_DOMAIN_VIDEO_TYPE_LAST
|
||||||
} virDomainVideoType;
|
} virDomainVideoType;
|
||||||
|
@ -101,7 +101,8 @@ VIR_ENUM_IMPL(qemuVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
|
|||||||
"", /* don't support vbox */
|
"", /* don't support vbox */
|
||||||
"qxl",
|
"qxl",
|
||||||
"", /* don't support parallels */
|
"", /* don't support parallels */
|
||||||
"" /* no need for virtio */);
|
"", /* no need for virtio */
|
||||||
|
"" /* don't support gop */);
|
||||||
|
|
||||||
VIR_ENUM_DECL(qemuDeviceVideo)
|
VIR_ENUM_DECL(qemuDeviceVideo)
|
||||||
|
|
||||||
@ -113,7 +114,8 @@ VIR_ENUM_IMPL(qemuDeviceVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
|
|||||||
"", /* don't support vbox */
|
"", /* don't support vbox */
|
||||||
"qxl-vga",
|
"qxl-vga",
|
||||||
"", /* don't support parallels */
|
"", /* don't support parallels */
|
||||||
"virtio-vga");
|
"virtio-vga",
|
||||||
|
"" /* don't support gop */);
|
||||||
|
|
||||||
VIR_ENUM_DECL(qemuDeviceVideoSecondary)
|
VIR_ENUM_DECL(qemuDeviceVideoSecondary)
|
||||||
|
|
||||||
@ -125,7 +127,8 @@ VIR_ENUM_IMPL(qemuDeviceVideoSecondary, VIR_DOMAIN_VIDEO_TYPE_LAST,
|
|||||||
"", /* don't support vbox */
|
"", /* don't support vbox */
|
||||||
"qxl",
|
"qxl",
|
||||||
"", /* don't support parallels */
|
"", /* don't support parallels */
|
||||||
"virtio-gpu-pci");
|
"virtio-gpu-pci",
|
||||||
|
"" /* don't support gop */);
|
||||||
|
|
||||||
VIR_ENUM_DECL(qemuSoundCodec)
|
VIR_ENUM_DECL(qemuSoundCodec)
|
||||||
|
|
||||||
|
@ -742,6 +742,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
|
|||||||
case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
|
case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
|
||||||
return pciFlags;
|
return pciFlags;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_VIDEO_TYPE_GOP:
|
||||||
case VIR_DOMAIN_VIDEO_TYPE_LAST:
|
case VIR_DOMAIN_VIDEO_TYPE_LAST:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
<value>qxl</value>
|
<value>qxl</value>
|
||||||
<value>parallels</value>
|
<value>parallels</value>
|
||||||
<value>virtio</value>
|
<value>virtio</value>
|
||||||
|
<value>gop</value>
|
||||||
</enum>
|
</enum>
|
||||||
</video>
|
</video>
|
||||||
<hostdev supported='yes'>
|
<hostdev supported='yes'>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user