Qemu support for the QXL driver and SPICE (#481)
* pmb.helpers.run: support running processes in background * enable QXL driver support in the linux kernel configurations so that we can also use SPICE to connect to the VM. QXL is a paravirtual graphics driver with 2D support The SPICE project aims to provide a complete open source solution for remote access to virtual machines in a seamless way. Both DRM_QXL and DRM_BOCHS are enabled as modules. According to [1], on Linux guests, the qxl and bochs_drm kernel modules must be loaded in order to gain a decent performance * qemu: add new option --spice to connect to VM using a SPICE client If specified, 'pmbootstrap qemu' will look for some SPICE client in the user's PATH and run qemu using the QXL driver. Currently supported spice clients are 'spicy' and 'remote-viewer' but adding support for more clients can be easily done. qemu with qxl support will run on port 8077/tcp, which doesn't belong to any well-known service and represents 'PM' in decimal. References: [0] https://www.linux-kvm.org/page/SPICE [1] https://wiki.archlinux.org/index.php/QEMU#qxl [2] https://wiki.archlinux.org/index.php/QEMU#SPICE [3] https://github.com/postmarketOS/pmbootstrap/issues/453 (partially fixed)
This commit is contained in:
parent
d48ca092b4
commit
c855ee095b
|
@ -1,6 +1,6 @@
|
|||
pkgname=device-qemu-aarch64
|
||||
pkgver=1
|
||||
pkgrel=2
|
||||
pkgrel=3
|
||||
pkgdesc="Simulated device in qemu with vexpress soc"
|
||||
url="https://github.com/postmarketOS"
|
||||
arch="noarch"
|
||||
|
@ -22,5 +22,5 @@ package() {
|
|||
"$pkgdir"/etc/network/interfaces
|
||||
}
|
||||
|
||||
sha512sums="56362f2482e94349c8ba821245dfbdec6e6ebc0ed47786ae333791faa8840fe6ef8d5a2f44b599dcfcbba499ed275546ebc2540428765e6eba2f146ba46795f5 deviceinfo
|
||||
sha512sums="692f5e0b5e8f10a88f5c81631377981eb9bdd22cce2e288f7849c67488f6d2b60ba6919db3c99907238c33507a58948e95fe5c4fd262fb2688da6060cd7129d9 deviceinfo
|
||||
d510ca304066840aa5e6c4fc71ded1b7e83012c93837fa39e37bdb873b3636230030d56f7aa50c93fc688f563cb4cb96c02ad333bbc45a400c1ebee1792a9dd4 interfaces"
|
||||
|
|
|
@ -8,7 +8,7 @@ deviceinfo_date=""
|
|||
deviceinfo_keyboard="true"
|
||||
deviceinfo_nonfree="????"
|
||||
deviceinfo_dtb=""
|
||||
deviceinfo_modules_initfs="virtio-gpu virtio_net"
|
||||
deviceinfo_modules_initfs="virtio-gpu virtio_net qxl drm_bochs"
|
||||
deviceinfo_external_disk="true"
|
||||
deviceinfo_external_disk_install="true"
|
||||
deviceinfo_flash_methods="none"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pkgname=device-qemu-amd64
|
||||
pkgver=1
|
||||
pkgrel=3
|
||||
pkgrel=4
|
||||
pkgdesc="Simulated device in qemu with an x86 platform"
|
||||
url="https://github.com/postmarketOS"
|
||||
arch="noarch"
|
||||
|
@ -22,5 +22,5 @@ package() {
|
|||
"$pkgdir"/etc/network/interfaces
|
||||
}
|
||||
|
||||
sha512sums="a02b2c46f913b148663b1252f71210a6ae1afa34af347664eac70570e9580b11257d23edfaa78797d03187e3bc3248c09c483e6c93ec0f0476d8b74af97e00d0 deviceinfo
|
||||
sha512sums="511fe8d2f1e4cf90d96a321568220ecf98bffd44b96339b200633a4f3c45b6b58e646c0971f82fbcd9829e4b66e62942a6ecc55ea03dd228ab76984b0ff0b92d deviceinfo
|
||||
d510ca304066840aa5e6c4fc71ded1b7e83012c93837fa39e37bdb873b3636230030d56f7aa50c93fc688f563cb4cb96c02ad333bbc45a400c1ebee1792a9dd4 interfaces"
|
||||
|
|
|
@ -8,7 +8,7 @@ deviceinfo_date=""
|
|||
deviceinfo_keyboard="true"
|
||||
deviceinfo_nonfree="????"
|
||||
deviceinfo_dtb=""
|
||||
deviceinfo_modules_initfs=""
|
||||
deviceinfo_modules_initfs="qxl drm_bochs"
|
||||
deviceinfo_external_disk="true"
|
||||
deviceinfo_external_disk_install="true"
|
||||
deviceinfo_flash_methods="none"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pkgname=device-qemu-vexpress
|
||||
pkgver=1
|
||||
pkgrel=9
|
||||
pkgrel=10
|
||||
pkgdesc="Simulated device in qemu with vexpress soc"
|
||||
url="https://github.com/postmarketOS"
|
||||
arch="noarch"
|
||||
|
@ -22,5 +22,5 @@ package() {
|
|||
"$pkgdir"/etc/network/interfaces
|
||||
}
|
||||
|
||||
sha512sums="a18ab789c19d8802be6a9e9c842f4c304f267bd78f46b096b4ba6609430d1544e0a9eca9bc22db67a0728efae3aad6c2def9f7e64157d31aeb31b4bb839076d5 deviceinfo
|
||||
sha512sums="4d49aca03d0c87ba1d35056c0985946bfeb9240130014f7e3b7155c38e4bfcdae8a67747969d1254fe064fe0b71847c537ca1e07bc5fd4173c6387270d72c4f2 deviceinfo
|
||||
d510ca304066840aa5e6c4fc71ded1b7e83012c93837fa39e37bdb873b3636230030d56f7aa50c93fc688f563cb4cb96c02ad333bbc45a400c1ebee1792a9dd4 interfaces"
|
||||
|
|
|
@ -8,7 +8,7 @@ deviceinfo_date=""
|
|||
deviceinfo_keyboard="true"
|
||||
deviceinfo_nonfree="????"
|
||||
deviceinfo_dtb="vexpress-v2p-ca9"
|
||||
deviceinfo_modules_initfs="amba-clcd virtio_net virtio_mmio ambakmi libps2 pcips2"
|
||||
deviceinfo_modules_initfs="amba-clcd virtio_net virtio_mmio ambakmi libps2 pcips2 qxl drm_bochs"
|
||||
deviceinfo_external_disk="true"
|
||||
deviceinfo_external_disk_install="true"
|
||||
deviceinfo_flash_methods="none"
|
||||
|
|
|
@ -18,7 +18,7 @@ case $pkgver in
|
|||
*.*.*) _kernver=${pkgver%.*};;
|
||||
*.*) _kernver=$pkgver;;
|
||||
esac
|
||||
pkgrel=2
|
||||
pkgrel=3
|
||||
|
||||
arch="all"
|
||||
pkgdesc="Mainline Linux for pmOS supported chipsets (OMAP)"
|
||||
|
@ -189,8 +189,8 @@ dev() {
|
|||
}
|
||||
|
||||
sha512sums="a557c2f0303ae618910b7106ff63d9978afddf470f03cb72aa748213e099a0ecd5f3119aea6cbd7b61df30ca6ef3ec57044d524b7babbaabddf8b08b8bafa7d2 linux-4.13.tar.xz
|
||||
03407ddd93db7188928ff7f689dff01afaa0119655e311440a8a286907d8f27bf058487b8f859a588f7f06bda98abe24998fc580f917df2f96f9b661905a54ce config-postmarketos.armhf
|
||||
d41363bc6b9878db95b44eb326f9fd0ea89b6f3364ff0e883a5142cfa2937e6b77e9b185c046cbd2c5d4e2f696349839836740f8dee6bd649ef995cbd756e08a config-postmarketos.aarch64
|
||||
8d3ea9743190680036d938a9d8ce8602f453152c69404741c70f1584075c111ba120d986b712fc509bbbe7882204292527738de9f03cf871c4911fff80a58d13 config-postmarketos.x86_64
|
||||
ab2b16db1aa1bb7550ac0c98215b549ca5f03db80b226effe05121f8175520f3a3accc4fb2b42c7ba1757282e77b844e11d8350d1a83e23821ae4e70da87996c config-postmarketos.armhf
|
||||
d49d5d01adb7f314d5649cf8d7e917eeca9ec286eff2687c6865a7fac46e18227e278ca8965ad29bd99320a676e167256dc1b4212c5702f819e4cd2cf40c33c9 config-postmarketos.aarch64
|
||||
4a95d0ddbf7023b41a3d438d439951b9878ce92194d3576c0ef3c1f1f8734331728c2aa03e736908d31bfcfd7c03b2760984714beb39573082916bc50c93c199 config-postmarketos.x86_64
|
||||
17c48bb7b4218297bd2be6faa5b6570ce1560a33385237a9962c0884d782c9a722a25a30077b6721d2943a9b98c29dcad6adfef718b0163c559c19a79519319b 0001-rx51-drm-regression-workaround.patch
|
||||
7c0675386c0906178661313d2dbaf644df9b43af31c4b8c8cc840c59b952c04c5768089782d79d84fd363e26b1824e05d1516a80b8cae663225fcb9b252d848a patch-4.13.3.xz"
|
||||
|
|
|
@ -3412,7 +3412,7 @@ CONFIG_DRM_EXYNOS_MIC=y
|
|||
# CONFIG_DRM_RCAR_DU is not set
|
||||
# CONFIG_DRM_RCAR_DW_HDMI is not set
|
||||
CONFIG_DRM_QXL=m
|
||||
# CONFIG_DRM_BOCHS is not set
|
||||
CONFIG_DRM_BOCHS=m
|
||||
CONFIG_DRM_VIRTIO_GPU=m
|
||||
CONFIG_DRM_MSM=m
|
||||
# CONFIG_DRM_MSM_REGISTER_LOGGING is not set
|
||||
|
|
|
@ -2966,6 +2966,7 @@ CONFIG_DRM_KMS_FB_HELPER=y
|
|||
CONFIG_DRM_FBDEV_EMULATION=y
|
||||
CONFIG_DRM_FBDEV_OVERALLOC=100
|
||||
# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
|
||||
CONFIG_DRM_TTM=m
|
||||
CONFIG_DRM_GEM_CMA_HELPER=y
|
||||
CONFIG_DRM_KMS_CMA_HELPER=y
|
||||
|
||||
|
@ -3027,8 +3028,8 @@ CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM=y
|
|||
# CONFIG_DRM_OMAP_PANEL_TPO_TD043MTEA1 is not set
|
||||
# CONFIG_DRM_OMAP_PANEL_NEC_NL8048HL11 is not set
|
||||
# CONFIG_DRM_TILCDC is not set
|
||||
# CONFIG_DRM_QXL is not set
|
||||
# CONFIG_DRM_BOCHS is not set
|
||||
CONFIG_DRM_QXL=m
|
||||
CONFIG_DRM_BOCHS=m
|
||||
# CONFIG_DRM_VIRTIO_GPU is not set
|
||||
# CONFIG_DRM_FSL_DCU is not set
|
||||
# CONFIG_DRM_STM is not set
|
||||
|
|
|
@ -3178,8 +3178,8 @@ CONFIG_DRM_TTM=y
|
|||
# CONFIG_DRM_MGAG200 is not set
|
||||
CONFIG_DRM_CIRRUS_QEMU=y
|
||||
# CONFIG_DRM_RCAR_DW_HDMI is not set
|
||||
# CONFIG_DRM_QXL is not set
|
||||
CONFIG_DRM_BOCHS=y
|
||||
CONFIG_DRM_QXL=m
|
||||
CONFIG_DRM_BOCHS=m
|
||||
# CONFIG_DRM_VIRTIO_GPU is not set
|
||||
CONFIG_DRM_PANEL=y
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import os
|
|||
|
||||
|
||||
def core(args, cmd, log_message, log, return_stdout, check=True,
|
||||
working_dir=None):
|
||||
working_dir=None, background=False):
|
||||
logging.debug(log_message)
|
||||
"""
|
||||
Run the command and write the output to the log.
|
||||
|
@ -35,29 +35,37 @@ def core(args, cmd, log_message, log, return_stdout, check=True,
|
|||
os.chdir(working_dir)
|
||||
|
||||
ret = None
|
||||
try:
|
||||
if log:
|
||||
if return_stdout:
|
||||
ret = subprocess.check_output(cmd).decode("utf-8")
|
||||
args.logfd.write(ret)
|
||||
else:
|
||||
subprocess.check_call(cmd, stdout=args.logfd,
|
||||
stderr=args.logfd)
|
||||
args.logfd.flush()
|
||||
else:
|
||||
logging.debug("*** output passed to pmbootstrap stdout, not" +
|
||||
" to this log ***")
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
except subprocess.CalledProcessError as exc:
|
||||
if check:
|
||||
if log:
|
||||
logging.debug("^" * 70)
|
||||
logging.info("NOTE: The failed command's output is above"
|
||||
" the ^^^ line in the logfile: " + args.log)
|
||||
raise RuntimeError("Command failed: " + log_message) from exc
|
||||
if background:
|
||||
if log:
|
||||
ret = subprocess.Popen(cmd, stdout=args.logfd, stderr=args.logfd)
|
||||
else:
|
||||
pass
|
||||
ret = subprocess.Popen(cmd)
|
||||
logging.debug("Started process in background with PID " + str(ret.pid))
|
||||
else:
|
||||
try:
|
||||
if log:
|
||||
if return_stdout:
|
||||
ret = subprocess.check_output(cmd).decode("utf-8")
|
||||
args.logfd.write(ret)
|
||||
else:
|
||||
subprocess.check_call(cmd, stdout=args.logfd,
|
||||
stderr=args.logfd)
|
||||
args.logfd.flush()
|
||||
else:
|
||||
logging.debug("*** output passed to pmbootstrap stdout, not" +
|
||||
" to this log ***")
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
except subprocess.CalledProcessError as exc:
|
||||
if check:
|
||||
if log:
|
||||
logging.debug("^" * 70)
|
||||
logging.info("NOTE: The failed command's output is above"
|
||||
" the ^^^ line in the logfile: " + args.log)
|
||||
raise RuntimeError("Command failed: " + log_message) from exc
|
||||
else:
|
||||
pass
|
||||
|
||||
if working_dir:
|
||||
os.chdir(working_dir_old)
|
||||
|
@ -65,7 +73,7 @@ def core(args, cmd, log_message, log, return_stdout, check=True,
|
|||
|
||||
|
||||
def user(args, cmd, log=True, working_dir=None, return_stdout=False,
|
||||
check=True):
|
||||
check=True, background=False):
|
||||
|
||||
if working_dir:
|
||||
msg = "% cd " + working_dir + " && " + " ".join(cmd)
|
||||
|
@ -73,13 +81,14 @@ def user(args, cmd, log=True, working_dir=None, return_stdout=False,
|
|||
msg = "% " + " ".join(cmd)
|
||||
|
||||
# TODO: maintain and check against a whitelist
|
||||
return core(args, cmd, msg, log, return_stdout, check, working_dir)
|
||||
return core(args, cmd, msg, log, return_stdout, check, working_dir,
|
||||
background)
|
||||
|
||||
|
||||
def root(args, cmd, log=True, working_dir=None, return_stdout=False,
|
||||
check=True):
|
||||
check=True, background=False):
|
||||
"""
|
||||
:param working_dir: defaults to args.work
|
||||
"""
|
||||
cmd = ["sudo"] + cmd
|
||||
return user(args, cmd, log, working_dir, return_stdout, check)
|
||||
return user(args, cmd, log, working_dir, return_stdout, check, background)
|
||||
|
|
|
@ -294,6 +294,11 @@ def arguments():
|
|||
help="guest RAM (default: 1024)")
|
||||
qemu.add_argument("-p", "--port", type=int, default=2222,
|
||||
help="ssh port (default: 2222)")
|
||||
qemu.add_argument("--spice", dest="use_spice",
|
||||
default=False, action="store_true",
|
||||
help="connect to the VM using SPICE (NOTE: you need to"
|
||||
" have a SPICE client installed in your host"
|
||||
" machine)")
|
||||
|
||||
# Use defaults from the user's config file
|
||||
args = parser.parse_args()
|
||||
|
|
|
@ -63,7 +63,49 @@ def which_qemu(args, arch):
|
|||
" run qemu.")
|
||||
|
||||
|
||||
def qemu_command(args, arch, device, img_path):
|
||||
def which_spice(args):
|
||||
"""
|
||||
Finds some SPICE executable or raises an exception otherwise
|
||||
:returns: tuple (spice_was_found, path_to_spice_executable)
|
||||
"""
|
||||
executables = ["remote-viewer", "spicy"]
|
||||
for executable in executables:
|
||||
if shutil.which(executable):
|
||||
return executable
|
||||
return None
|
||||
|
||||
|
||||
def spice_command(args):
|
||||
"""
|
||||
Generate the full SPICE command with arguments connect to
|
||||
the virtual machine
|
||||
:returns: tuple (dict, list), configuration parameters and spice command
|
||||
"""
|
||||
parameters = {
|
||||
"spice_addr": "127.0.0.1",
|
||||
"spice_port": "8077"
|
||||
}
|
||||
if not args.use_spice:
|
||||
parameters["enable_spice"] = False
|
||||
return parameters, []
|
||||
spice_binary = which_spice(args)
|
||||
if not spice_binary:
|
||||
parameters["enable_spice"] = False
|
||||
return parameters, []
|
||||
spice_addr = parameters["spice_addr"]
|
||||
spice_port = parameters["spice_port"]
|
||||
commands = {
|
||||
"spicy": ["spicy", "-h", spice_addr, "-p", spice_port],
|
||||
"remote-viewer": [
|
||||
"remote-viewer",
|
||||
"spice://" + spice_addr + "?port=" + spice_port
|
||||
]
|
||||
}
|
||||
parameters["enable_spice"] = True
|
||||
return parameters, commands[spice_binary]
|
||||
|
||||
|
||||
def qemu_command(args, arch, device, img_path, config):
|
||||
"""
|
||||
Generate the full qemu command with arguments to run postmarketOS
|
||||
"""
|
||||
|
@ -132,6 +174,13 @@ def qemu_command(args, arch, device, img_path):
|
|||
else:
|
||||
logging.info("Warning: qemu is not using KVM and will run slower!")
|
||||
|
||||
# QXL / SPICE (2D acceleration support)
|
||||
if config["enable_spice"]:
|
||||
command += ["-vga", "qxl"]
|
||||
command += ["-spice",
|
||||
"port={spice_port},addr={spice_addr}".format(**config) +
|
||||
",disable-ticketing"]
|
||||
|
||||
return command
|
||||
|
||||
|
||||
|
@ -179,18 +228,20 @@ def run(args):
|
|||
arch = pmb.parse.arch.uname_to_qemu(args.arch_native)
|
||||
if args.arch:
|
||||
arch = pmb.parse.arch.uname_to_qemu(args.arch)
|
||||
logging.info("Running postmarketOS in QEMU VM (" + arch + ")")
|
||||
|
||||
device = pmb.parse.arch.qemu_to_pmos_device(arch)
|
||||
img_path = system_image(args, device)
|
||||
spice_parameters, command_spice = spice_command(args)
|
||||
|
||||
# Workaround: qemu runs as local user and needs write permissions in the
|
||||
# system image, which is owned by root
|
||||
if not os.access(img_path, os.W_OK):
|
||||
pmb.helpers.run.root(args, ["chmod", "666", img_path])
|
||||
|
||||
command = qemu_command(args, arch, device, img_path)
|
||||
run_spice = spice_parameters["enable_spice"]
|
||||
command = qemu_command(args, arch, device, img_path, spice_parameters)
|
||||
|
||||
logging.info("Running postmarketOS in QEMU VM (" + arch + ")")
|
||||
logging.info("Command: " + " ".join(command))
|
||||
|
||||
if args.image_size:
|
||||
|
@ -200,9 +251,31 @@ def run(args):
|
|||
" the system image size when you run out of space!")
|
||||
|
||||
print()
|
||||
logging.info("You can connect to the Virtual Machine using the"
|
||||
logging.info("You can connect to the virtual machine using the"
|
||||
" following services:")
|
||||
logging.info("(ssh) ssh -p " + str(args.port) + " user@localhost")
|
||||
logging.info("(telnet) telnet localhost " + str(args.port + 1))
|
||||
logging.info("(telnet debug) telnet localhost " + str(args.port + 2))
|
||||
pmb.helpers.run.user(args, command)
|
||||
|
||||
# SPICE related messages
|
||||
if not run_spice:
|
||||
if args.use_spice:
|
||||
logging.warning("WARNING: Could not find any SPICE client (spicy,"
|
||||
" remote-viewer) in your PATH, starting without"
|
||||
" SPICE support!")
|
||||
else:
|
||||
logging.info("NOTE: Consider using --spice for potential"
|
||||
" performance improvements (2d acceleration)")
|
||||
|
||||
try:
|
||||
process = pmb.helpers.run.user(args, command, background=run_spice)
|
||||
|
||||
# Launch SPICE client
|
||||
if run_spice:
|
||||
logging.info("Command: " + " ".join(command_spice))
|
||||
pmb.helpers.run.user(args, command_spice)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
if process:
|
||||
process.terminate()
|
||||
|
|
Loading…
Reference in New Issue