Python bindings to the VirtualBox SOAP API.
Provides a Python SOAP client using zeep
to the VirtualBox SOAP API, with Pythonic bindings, and models for object-oriented usage.
Several methods have been added to models to assist with common operations, and simplify many interface methods.
Command-line interface:
Web (HTTP) interface:
vbox_api.interface
contains all relevant classes to communicate with the VirtualBox API.
vbox_api.models
defines classes to use an interface in an object-oriented approach (see below).
vbox_api.cli
contains an entry point for an interactive command-line interface and functions to parse arguments.
vbox_api.http
includes a Flask application to view and manage virtual machines over HTTP.
vbox_api.constants
defines many enumerations, mostly generated from the VirtualBox WSDL XML, with added enumerations for those not currently specified but used internally, such as MachineFrontend
.
These can be used as a reference for expected values to/from the VirtualBox interface, when type hinting or passing values.
vbox_api.helpers
includes a class, WebSocketProxyProcess
, to wrap websockify.WebSocketProxy
, allowing remote control of a virtual machine over HTTP, accessible from the web interface.
vrde_ext_pack
must be set to VNC
and noVNC must be available.
Models allow properties to be obtained and set in an object-oriented fashion, e.g. machine.name
, instead of IMachine_getName(handle)
.
To do this, BaseModel
defines both a __getattr__
and a __setattr__
method, which call the relevant interface method for the requested attribute to either get or set, respectively.
Additionally, the to_dict
and from_dict
methods allow multiple properties to be handled at once.
Any valid interface name can be used to create a model, using BaseModel.from_name
.
The interface is passed via a Context
object, along with the handle of the model.
All methods of the interface are bound to this model, using functools.partial
to implictly pass its handle, then wrapped to return model instances.
BaseModel
also implements __str__
, allowing models to be passed directly to interface methods as a handle.
Models are automatically instantiated from returned results, by obtaining the interface name from the returned handle, using ManagedObjectRef.get_interface_name
.
Alternatively, a passed value can be matched by string comparison to an existing interface name.
A metaclass is used to ensure that objects with the same handle and class are not recreated; the same object is returned.
The instances are stored in a WeakValueDictionary
, allowing them to be garbage collected when no longer referenced.
For example:
machine = api.machines[0]
assert machine is Machine(api.ctx, machine.handle)
After cloning the repository with: git clone https://github.com/Zedeldi/vbox-api.git
- Install project:
pip install .
- Run:
vbox-api-cli
(CLI) orvbox-api-http
(HTTP)
- Install dependencies:
pip install -r requirements.txt
- Run:
python -m vbox_api.cli
(CLI) orpython -m vbox_api.http
(HTTP)
- Zeep - SOAP client
- Flask - HTTP interface
- Pillow - image support
- psutil - process information
- websockify - remote control
The server application can be bundled with PyInstaller, by adding the required static files and templates for Flask to the bundle.
Additionally, vbox_api.http.gui
provides a simple wrapper using flaskwebgui, to serve and open the Flask application in a browser window.
pyinstaller \
--name "vbox-api-gui" \
--add-data "vbox_api/http/static:vbox_api/http/static" \
--add-data "vbox_api/http/templates:vbox_api/http/templates" \
--onefile \
vbox_api/http/gui.py
- Build and install the package:
makepkg -si
- Run:
vbox-api-cli
(CLI) orvbox-api-http
(HTTP)- The HTTP interface can also be started using a systemd unit:
systemctl start vbox-api-http
- The HTTP interface can also be started using a systemd unit:
Note: if the optional dependency novnc
is installed from the AUR, HTTP remote control will be available out of the box.
Dockerfiles are supplied in docker/
, to run both vbox-api-http
and vboxwebsrv
in a container.
If you already have VirtualBox installed to your machine, you can build and start vbox-api-http
in a Docker container easily.
The VirtualBox container requires the host kernel modules to be installed for /dev/vboxdrv
to be available.
Build vbox-api image, passing current directory as the build context:
docker build -t "vbox-api" -f docker/api/Dockerfile .
Build VirtualBox image, optionally passing additional build arguments:
docker build -t "virtualbox" -f docker/virtualbox/Dockerfile .
docker build -t "virtualbox" --build-arg USER="user" --build-arg PASS="password" -f docker/virtualbox/Dockerfile .
docker build -t "virtualbox" --build-arg PACMAN_ARGS="--disable-download-timeout" -f docker/virtualbox/Dockerfile .
Run vbox-api-http
in a container interactively, with host network:
docker run -it --rm --network=host "vbox-api"
Run vboxwebsrv
in a container interactively, with host network (note: VirtualBox host kernel modules must be installed):
docker run -it --rm --network=host --device /dev/vboxdrv:/dev/vboxdrv -e DISPLAY=unix:0 "virtualbox"
Ensure that vboxwebsrv
is running as the intended user.
The virtualbox
package also provides a systemd unit for this: systemctl start vboxweb
.
In the following examples, api
refers to a VBoxAPI
(or VirtualBox
model) instance.
Get machine information:
for machine in api.machines:
print(machine.to_dict())
Wait for machine to start in headless mode:
progress = machine.start(front_end="headless") # or MachineFrontend.HEADLESS
progress.wait_for_completion(-1)
Write-lock machine and set machine name:
with machine.with_lock(save_settings=True) as locked_machine:
locked_machine.name = "Machine Name"
# or
locked_machine.set_name("Machine Name")
assert machine.name == "Machine Name"
Create machine with default settings for Windows 11:
machine = api.create_machine_with_defaults(
name="Windows 11",
os_type_id="Windows11_64",
)
Create machine from Windows 11 ISO and start unattended installation:
machine = api.create_machine_from_iso(
iso_path="Win11_23H2_EnglishInternational_x64.iso",
name="Windows 11",
unattended_options={
"user": "username",
"password": "password",
"install_guest_additions": True,
},
)
machine.attach_medium(hard_disk) # See Medium examples
machine.start()
Clone machine:
cloned_machine = machine.clone(f"{machine.name} - Clone")
Interact with guest OS of machine:
with machine.with_lock() as locked_machine:
guest = locked_machine.session.console.guest
session = guest.create_session("username", "password", "domain", "session_name")
# Wait for session.status to be GuestSessionStatus.STARTED
progress = session.copy_from_guest(r"C:\path\to\copy", [], FileCopyFlag.NONE, "/path/to/destination/")
process = session.process_create(r"C:\path\to\file.exe", ["argument"], ["var=1"], ProcessCreateFlag.NONE, 0)
Teleport machine to another on the same host, with a password:
# Configure then start target machine
target_machine.teleport_listen(port=6000, password="password")
target_machine.start()
# Start then teleport source machine to target machine
source_machine.start()
source_machine.teleport_to(host="localhost", port=6000, password="password")
Get medium information:
for medium in api.mediums: # or specify dvd_images, floppy_images, hard_disks
print(medium.to_dict())
Create hard-disk medium:
medium = api.create_medium_with_defaults(
location="/path/to/medium.vdi",
logical_size=1024 ** 4, # 1 TiB
format_="VDI",
)
vbox-api
has been tested successfully on Arch Linux and Windows 10.
Unit tests can be run using pytest, though tests require authentication for the VirtualBox interface: python -m pytest
Please contribute by raising an issue or submitting a pull request, whether for code or documentation.
Source code is formatted using black, and type hints should be added where possible.
If there are any questions, please do not hesitate to ask. All contributions are welcome!
For VirtualBox v7.1.0
onwards (released 09/09/2024), use v2.0.0
or above of vbox-api
.
v7.1.0
was a major update, causing some breaking changes with their API, specifically with the introduction of PlatformProperties
.
For previous versions of VirtualBox, use v1.5.3
or below.
For more information, see the VirtualBox Changelog.
- @Zedeldi - creator
- VirtualBox - well, duh.
- API Documentation - reference for interface methods and properties
- Bootstrap - used for HTTP interface
- noVNC/websockify - support for HTTP remote control
- See libraries for list of dependencies
- vboxwebber - VirtualBox SOAP API client for Python
- phpVirtualBox - web interface to manage and access Virtualbox machines
- RemoteBox - VirtualBox GUI (GTK3) client
vbox-api
is licensed under the MIT Licence for everyone to use, modify and share freely.
This project is distributed in the hope that it will be useful, but without any warranty.
The VirtualBox logo is licensed under the GPL-2.0.
If you found this project useful, please consider donating. Any amount is greatly appreciated! Thank you 😃