forked from Mirror/pmbootstrap
* 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)
94 lines
3 KiB
Python
94 lines
3 KiB
Python
"""
|
|
Copyright 2017 Oliver Smith
|
|
|
|
This file is part of pmbootstrap.
|
|
|
|
pmbootstrap is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
pmbootstrap is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
import subprocess
|
|
import logging
|
|
import os
|
|
|
|
|
|
def core(args, cmd, log_message, log, return_stdout, check=True,
|
|
working_dir=None, background=False):
|
|
logging.debug(log_message)
|
|
"""
|
|
Run the command and write the output to the log.
|
|
|
|
:param check: raise an exception, when the command fails
|
|
"""
|
|
|
|
if working_dir:
|
|
working_dir_old = os.getcwd()
|
|
os.chdir(working_dir)
|
|
|
|
ret = None
|
|
|
|
if background:
|
|
if log:
|
|
ret = subprocess.Popen(cmd, stdout=args.logfd, stderr=args.logfd)
|
|
else:
|
|
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)
|
|
return ret
|
|
|
|
|
|
def user(args, cmd, log=True, working_dir=None, return_stdout=False,
|
|
check=True, background=False):
|
|
|
|
if working_dir:
|
|
msg = "% cd " + working_dir + " && " + " ".join(cmd)
|
|
else:
|
|
msg = "% " + " ".join(cmd)
|
|
|
|
# TODO: maintain and check against a whitelist
|
|
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, background=False):
|
|
"""
|
|
:param working_dir: defaults to args.work
|
|
"""
|
|
cmd = ["sudo"] + cmd
|
|
return user(args, cmd, log, working_dir, return_stdout, check, background)
|