No module named 'xpcom' with Python3 on CentOS 7 (all documented solutions attempted)
Hello,
I'm yet another person running into the ModuleNotFoundError: No module named 'xpcom' error. I've tried every solution from the previous issues but nothing seems to work. I'm hoping that I made the mistake here and a second pair of eyes can find it.
Below is a slightly truncated output of me recreating my build script in a normal terminal. The binaries (except for the SDK) are installed from RPMFusion.
[root@localhost ~]# uname -a
Linux localhost 3.10.0-957.27.2.el7.x86_64 #1 SMP Mon Jul 29 17:46:05 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
[root@localhost ~]# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[root@localhost ~]# semanage port -a -t http_port_t -p tcp 18083
[root@localhost ~]# yum install -y VirtualBox VirtualBox-webservice akmod-VirtualBox
... snip ...
===============================================================================================
Package Arch Version Repository Size
===============================================================================================
Installing:
VirtualBox x86_64 6.0.10-1.el7 rpmfusion-free-updates 2.3 M
VirtualBox-webservice x86_64 6.0.10-1.el7 rpmfusion-free-updates 5.7 M
akmod-VirtualBox x86_64 6.0.10-1.el7 rpmfusion-free-updates 57 k
Installing for dependencies:
SDL x86_64 1.2.15-14.el7 base 204 k
VirtualBox-kmodsrc noarch 6.0.10-1.el7 rpmfusion-free-updates 888 k
VirtualBox-server x86_64 6.0.10-1.el7 rpmfusion-free-updates 40 M
akmods noarch 0.5.6-11.el7 epel 20 k
gsoap x86_64 2.8.16-12.el7 epel 247 k
kmodtool noarch 1-24.el7 epel 13 k
libvpx x86_64 1.3.0-5.el7_0 base 498 k
pcre2-utf16 x86_64 10.23-2.el7 base 189 k
qt5-qtbase x86_64 5.9.2-3.el7 base 3.3 M
qt5-qtbase-common noarch 5.9.2-3.el7 base 26 k
qt5-qtbase-gui x86_64 5.9.2-3.el7 base 5.2 M
qt5-qtx11extras x86_64 5.9.2-1.el7 base 27 k
time x86_64 1.7-45.el7 base 30 k
xcb-util-image x86_64 0.4.0-2.el7 base 15 k
xcb-util-keysyms x86_64 0.4.0-1.el7 base 10 k
xcb-util-renderutil x86_64 0.3.9-3.el7 base 12 k
xcb-util-wm x86_64 0.4.1-5.el7 base 25 k
... snip ...
Complete!
[root@localhost ~]# akmods --kernels $(uname -r)
Checking kmods exist for 3.10.0-957.27.2.el7.x86_64 [ OK ]
[root@localhost ~]# systemctl restart systemd-modules-load.service
[root@localhost ~]# mkdir /home/virtualbox
[root@localhost ~]# useradd -m -N -d /home/virtualbox -g vboxusers -Z unconfined_u -c "VirtualBox User" vbox
useradd: warning: the home directory already exists.
Not copying any file from skel directory into it.
[root@localhost ~]# sudo -u vbox cp -v /etc/skel/.bash /home/virtualbox/
cp: cannot stat ‘/etc/skel/.bash’: No such file or directory
[root@localhost ~]# sudo -u vbox cp -v /etc/skel/.bash* /home/virtualbox/
‘/etc/skel/.bash_logout’ -> ‘/home/virtualbox/.bash_logout’
‘/etc/skel/.bash_profile’ -> ‘/home/virtualbox/.bash_profile’
‘/etc/skel/.bashrc’ -> ‘/home/virtualbox/.bashrc’
[root@localhost ~]# chown vbox:vboxusers /home/virtualbox/.*
[root@localhost ~]# passwd vbox
Changing password for user vbox.
New password:
BAD PASSWORD: The password fails the dictionary check - it is based on a dictionary word
Retype new password:
passwd: all authentication tokens updated successfully.
[root@localhost ~]# cp -v /usr/lib/systemd/system/vboxweb.service /etc/systemd/system/vboxweb-custom.service
‘/usr/lib/systemd/system/vboxweb.service’ -> ‘/etc/systemd/system/vboxweb-custom.service’
[root@localhost ~]# sed -i "s,\[Service\],[Service]\nUser=vbox\nGroup=vboxusers\nEnvironment=VBOXWEB_USER=vbox,g ; s#/run/vboxweb.pid#/dev/shm/vboxweb.pid#g; s#--pidfile#--host 127.0.0.1 --pidfile" /etc/systemd/system/vboxweb-custom.service
sed: -e expression #1, char 168: unterminated `s' command
[root@localhost ~]# sed -i "s,\[Service\],[Service]\nUser=vbox\nGroup=vboxusers\nEnvironment=VBOXWEB_USER=vbox,g ; s#/run/vboxweb.pid#/dev/shm/vboxweb.pid#g; s#--pidfile#--host 127.0.0.1 --pidfile#g" /etc/systemd/system/vboxweb-custom.service
[root@localhost ~]# cat /etc/systemd/system/vboxweb-custom.service
[Unit]
Description=VirtualBox Web Service
After=network.target
[Service]
User=vbox
Group=vboxusers
Environment=VBOXWEB_USER=vbox
Type=forking
ExecStart=/usr/bin/vboxwebsrv --host 127.0.0.1 --pidfile /dev/shm/vboxweb.pid --background
ExecStopPost=/usr/bin/rm /dev/shm/vboxweb.pid
PIDFile=/dev/shm/vboxweb.pid
[Install]
WantedBy=multi-user.target
[root@localhost ~]# curl -O https://download.virtualbox.org/virtualbox/6.0.10/VirtualBoxSDK-6.0.10-132072.zip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 10.3M 100 10.3M 0 0 16.8M 0 --:--:-- --:--:-- --:--:-- 16.8M
[root@localhost ~]# unzip -d /home/virtualbox/ VirtualBoxSDK-6.0.10-132072.zip
Archive: VirtualBoxSDK-6.0.10-132072.zip
... snip ...
[root@localhost ~]# chown -R vbox:vboxusers /home/virtualbox/sdk/
[root@localhost ~]# cd /home/virtualbox/sdk/
bindings/ docs/ installer/ rdpweb/
[root@localhost ~]# cd /home/virtualbox/sdk/installer/
[root@localhost installer]# ls
vboxapi vboxapisetup.py
[root@localhost installer]# export VBOX_INSTALL_PATH=/usr/lib64/virtualbox/
[root@localhost installer]# python3 vboxapisetup.py install
running install
running build
running build_py
creating build
creating build/lib
creating build/lib/vboxapi
copying vboxapi/VirtualBox_constants.py -> build/lib/vboxapi
copying vboxapi/__init__.py -> build/lib/vboxapi
running install_lib
creating /usr/local/lib/python3.6/site-packages/vboxapi
copying build/lib/vboxapi/VirtualBox_constants.py -> /usr/local/lib/python3.6/site-packages/vboxapi
copying build/lib/vboxapi/__init__.py -> /usr/local/lib/python3.6/site-packages/vboxapi
byte-compiling /usr/local/lib/python3.6/site-packages/vboxapi/VirtualBox_constants.py to VirtualBox_constants.cpython-36.pyc
byte-compiling /usr/local/lib/python3.6/site-packages/vboxapi/__init__.py to __init__.cpython-36.pyc
running install_egg_info
Writing /usr/local/lib/python3.6/site-packages/vboxapi-1.0-py3.6.egg-info
[root@localhost installer]# pip3 install virtualbox
Collecting virtualbox
Downloading https://files.pythonhosted.org/packages/bc/42/9535725559e8d7edae2223e5139a1b0827395e4d734fba6a88ae9d85fe1b/virtualbox-2.0.0-py2.py3-none-any.whl (250kB)
|████████████████████████████████| 256kB 4.4MB/s
Installing collected packages: virtualbox
Successfully installed virtualbox-2.0.0
[root@localhost installer]# python3 -V
Python 3.6.8
[root@localhost installer]# python3
Python 3.6.8 (default, Apr 25 2019, 21:02:35)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import virtualbox
>>> vbox = virtualbox.VirtualBox()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/virtualbox/library_ext/vbox.py", line 22, in __init__
manager = virtualbox.Manager()
File "/usr/local/lib/python3.6/site-packages/virtualbox/__init__.py", line 145, in __init__
self.manager = vboxapi.VirtualBoxManager(mtype, mparams)
File "/home/virtualbox/sdk/installer/vboxapi/__init__.py", line 989, in __init__
self.platform = PlatformXPCOM(dPlatformParams)
File "/home/virtualbox/sdk/installer/vboxapi/__init__.py", line 750, in __init__
import xpcom.vboxxpcom
ModuleNotFoundError: No module named 'xpcom'
>>>
Have you tried installing from a multi-distro package?
download.virtualbox.org/virtualbox/6.0.10/VirtualBox-6.0.10-132072-Linux_amd64.run
So, I managed to get it to work with the multi-distro, but it took some pretty jank steps that I'm pretty sure is all Oracle's fault.
This is delicate enough that I can't really use it for my use case where I do automated builds, so I'm probably just going to either call the SOAP API directly or just call VBoxManage.
But here it is documented for posterity if anyone googles this, here's the steps you need to get it working:
# Tell SELinux to allow vboxweb.
semanage port -a -t http_port_t -p tcp 18083
# Download the multi-distro installer from oracle
vboxlink=$(curl -sL https://www.virtualbox.org/wiki/Linux_Downloads | grep -oP 'https.//download.virtualbox.org/virtualbox/.*VirtualBox-.*-Linux_amd64.run')
vboxfilename=${vboxlink##*/}
curl -LO $vboxlink
chmod +x $vboxfilename
./$vboxfilename
# I use a non-root user for the vbox web service. This isn't required but the web service is
# broken out of the box and swapping out 'root' for the below doesn't work for somee reason,
# while a unprivileged vbox user does
useradd -m -N -d /home/vbox -g vboxusers -Z unconfined_u -c "VirtualBox User" vbox
cp -v /opt/VirtualBox/vboxweb-service.sh /opt/VirtualBox/vboxweb-service.bak
# vboxweb supports unprvileged users, but by default tries to write the pidfile to somewhere
# that's root writeable only it fails. I changed this to /dev/shm, but anywhere that your vbox user
# can write works.
sed -i "s,PIDFILE=\"/var/run/..SCRIPTNAME.,PIDFILE=\"/dev/shm/vboxweb-service.pid,g" /opt/VirtualBox/vboxweb-service.sh
# If the VBOXWEB_USER environment variable isn't set the service script exits immediately
# with no error message ... needed bash -x to figure this one out. I set mine to the vbox user
cp -v /usr/lib/systemd/system/vboxweb-service.service /etc/systemd/system/vboxweb-custom.service
systemctl disable vboxweb-service.service
systemctl stop vboxweb-service.service
sed -i "s,\[Service\],[Service]\nEnvironment=VBOXWEB_USER=vbox,g" /etc/systemd/system/vboxweb-custom.service
systemctl enable vboxweb-custom.service
systemctl start vboxweb-custom.service
# Next is the secret sauce. The multi install only has Python 2 and Python 26(!) modules.
# Installing the python36-VirtualBox package from RPMFusion and copying over the shared object
# fixes it. Just copying over the .so to a new install doesn't work. There's something that the
# RPM or one of it's dependencies does that gets it working.
yum install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm
yum install -y python36-VirtualBox
cp /usr/lib64/virtualbox/VBoxPython3* /opt/VirtualBox/
export VBOX_INSTALL_PATH=/opt/VirtualBox/
pushd /opt/VirtualBox/sdk/installer
python3 vboxapisetup.py install
pip3 install virtualbox