Build and run a Python3 Hello program on Unikraft. Follow the instructions below to set up, configure, build and run Python3 Hello. Make sure you installed the requirements.
For a quick setup, run the commands below. Note that you still need to install the requirements.
To build and run the application for x86_64, use the commands below:
test -d ../repos/unikraft || git clone https://github.com/unikraft/unikraft ....//repos/unikraft
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
test -d ../repos/libs/lwip || git clone https://github.com/unikraft/lib-lwip ../repos/libs/lwip
test -d ../repos/libs/python3 || git clone https://github.com/unikraft/lib-python3 ../repos/libs/python3
test -d ../repos/libs/compiler-rt || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rt
make distclean
> /tmp/defconfig echo 'CONFIG_PLAT_KVM=y
CONFIG_KVM_VMM_QEMU=y
CONFIG_ARCH_X86_64=y
CONFIG_LIBPYTHON3=y
CONFIG_LIBPYTHON3_MAIN_FUNCTION=y
CONFIG_LIBVFSCORE=y
CONFIG_LIBVFSCORE_AUTOMOUNT_UP=y
CONFIG_LIBRAMFS=y
CONFIG_LIBUKCPIO=y
CONFIG_STACK_SIZE_PAGE_ORDER=10
CONFIG_LIBPOSIX_ENVIRON=y
CONFIG_LIBPOSIX_ENVIRON_LIBPARAM=y'
UK_DEFCONFIG=/tmp/defconfig make defconfig
make -j $(nproc)
test -d ./rootfs/ || docker build -o ./rootfs -f Dockerfile .
test -f initrd.cpio || ../repos/unikraft/support/scripts/mkcpio initrd.cpio ./rootfs/
qemu-system-x86_64 \
-nographic \
-m 256 \
-cpu max \
-append "python3-hello_qemu-x86_64 vfs.fstab=[ \"initrd0:/:extract::ramfs=1:\" ] env.vars=[ PYTHONPATH=\"/usr/local/lib/python3.10:/usr/local/lib/python3.10/site-packages\" ] -- /app/hello.py" \
-kernel out/python3-hello_qemu-x86_64 \
-initrd ./initrd.cpioThis will configure, build and run Python3 Hello on Unikraft. You can see how to test it in the "Test" section. To close the virtual machine, see the instructions in the "Close QEMU" section.
To do the same for AArch64, run the commands below:
test -d ../repos/unikraft || git clone https://github.com/unikraft/unikraft ....//repos/unikraft
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
test -d ../repos/libs/lwip || git clone https://github.com/unikraft/lib-lwip ../repos/libs/lwip
test -d ../repos/libs/python3 || git clone https://github.com/unikraft/lib-python3 ../repos/libs/python3
test -d ../repos/libs/compiler-rt || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rt
make distclean
> /tmp/defconfig echo 'CONFIG_PLAT_KVM=y
CONFIG_KVM_VMM_QEMU=y
CONFIG_ARCH_ARM_64=y
CONFIG_LIBPYTHON3=y
CONFIG_LIBPYTHON3_MAIN_FUNCTION=y
CONFIG_LIBVFSCORE=y
CONFIG_LIBVFSCORE_AUTOMOUNT_UP=y
CONFIG_LIBRAMFS=y
CONFIG_LIBUKCPIO=y
CONFIG_STACK_SIZE_PAGE_ORDER=10
CONFIG_LIBPOSIX_ENVIRON=y
CONFIG_LIBPOSIX_ENVIRON_LIBPARAM=y
CONFIG_ARM64_ERRATUM_858921=n
CONFIG_ARM64_ERRATUM_835769=n
CONFIG_ARM64_ERRATUM_843419=n'
UK_DEFCONFIG=/tmp/defconfig make defconfig
make -j $(nproc)
test -d ./rootfs/ || docker build -o ./rootfs -f Dockerfile .
test -f initrd.cpio || ../repos/unikraft/support/scripts/mkcpio initrd.cpio ./rootfs/
qemu-system-aarch64 \
-nographic \
-machine virt \
-m 256 \
-cpu max \
-append "python3-hello_qemu-arm64 vfs.fstab=[ \"initrd0:/:extract::ramfs=1:\" ] env.vars=[ PYTHONPATH=\"/usr/local/lib/python3.10:/usr/local/lib/python3.10/site-packages\" ] -- /app/hello.py" \
-kernel out/python3-hello_qemu-arm64 \
-initrd ./initrd.cpioSimilar to the x86_64 build, this will configure, build and run Python3 Hello on Unikraft.
Information about every step and about other types of builds is detailed below.
Set up the required repositories.
Clone them in ../repos/ if not already cloned:
test -d ../repos/unikraft || git clone https://github.com/unikraft/unikraft ....//repos/unikraft
test -d ../repos/libs/musl || git clone https://github.com/unikraft/lib-musl ../repos/libs/musl
test -d ../repos/libs/lwip || git clone https://github.com/unikraft/lib-lwip ../repos/libs/lwip
test -d ../repos/libs/python3 || git clone https://github.com/unikraft/lib-python3 ../repos/libs/python3
test -d ../repos/libs/compiler-rt || git clone https://github.com/unikraft/lib-compiler-rt ../repos/libs/compiler-rtIf you want use a custom variant of a repository (e.g. apply your own patch, make modifications), update it accordingly in the ../repos/ directory.
While not strictly required, it is safest to clean the previous build artifacts:
make distcleanTo configure the kernel, use:
make menuconfigIn the console menu interface, choose the target architecture (x86_64 or ARMv8 or ARMv7) and platform (Xen or KVM/QEMU or KVM/Firecracker).
After choosing the target architecture and the platform, go back to the Architecture Selection menu entry and update the Stack size page order to 10.
Then save the configuration.
The end result will be the creation of the .config configuration file.
Build the application for the current configuration:
make -j $(nproc)This results in the creation of the out/ directory storing the build artifacts.
The unikernel application image file is out/python3-hello_<plat>-<arch>, where <plat> is the platform name (qemu, fc, xen), and <arch> is the architecture (x86_64 or arm64).
If you want to use a different compiler, such as a Clang or a different GCC version, pass the CC variable to make.
To build with Clang, use the commands below:
make properclean
make CC=clang -j $(nproc)Note that Clang >= 14 is required to build Unikraft.
To build with another GCC version, use the commands below:
make properclean
make CC=gcc-<version> -j $(nproc)where <version> is the GCC version, such as 11, 12.
Note that GCC >= 8 is required to build Unikraft.
The filesystem is to be packed into initrd.cpio, an initial ramdisk CPIO file.
First create the root filesystem from the Dockerfile into the ./rootfs/ directory:
rm -fr ./rootfs
docker build -o ./rootfs -f Dockerfile .Then pack the ./rootfs/ directory in the initrd.cpio file:
rm -f initrd.cpio
../repos/unikraft/support/scripts/mkcpio initrd.cpio ./rootfs/Doing a new configuration, or a new build, may require cleaning up the configuration and build artifacts.
In order to remove the build artifacts, use:
make cleanIn order to remove fetched files also, that is the removal of the out/ directory, use:
make propercleanIn order to remove the generated .config file as well, use:
make distcleanRun the resulting image using the corresponding platform tool. Firecracker requires KVM support. Xen requires a system with Xen installed.
A successful run will show a message such as the one below:
Powered by
o. .o _ _ __ _
Oo Oo ___ (_) | __ __ __ _ ' _) :_
oO oO ' _ `| | |/ / _)' _` | |_| _)
oOo oOO| | | | | (| | | (_) | _) :_
OoOoO ._, ._:_:_,\_._, .__,_:_, \___)
Calypso 0.17.0~ca507107
Hello from Unikraft!
This means that Python3 Hello runs on Unikraft.
The shutdown mechanism doesn't currently work for Python3; To close the virtual machine, see the instructions in the "Close QEMU" section.
qemu-system-x86_64 \
-nographic \
-m 256 \
-cpu max \
-append "python3-hello_qemu-x86_64 vfs.fstab=[ \"initrd0:/:extract::ramfs=1:\" ] env.vars=[ PYTHONPATH=\"/usr/local/lib/python3.10:/usr/local/lib/python3.10/site-packages\" ] -- /app/hello.py" \
-kernel out/python3-hello_qemu-x86_64 \
-initrd ./initrd.cpioqemu-system-aarch64 \
-nographic \
-machine virt \
-m 256 \
-cpu max \
-append "python3-hello_qemu-arm64 vfs.fstab=[ \"initrd0:/:extract::ramfs=1:\" ] env.vars=[ PYTHONPATH=\"/usr/local/lib/python3.10:/usr/local/lib/python3.10/site-packages\" ] -- /app/hello.py" \
-kernel out/python3-hello_qemu-arm64 \
-initrd ./initrd.cpiorm -f firecracker.socket
firecracker-x86_64 --config-file fc.x86_64.json --api-sock firecracker.socketThe user running the above command must be able to use KVM.
Typically this means being part of the kvm group.
Otherwise, run the command above as root or prefixed by sudo.
rm -f firecracker.socket
firecracker-aarch64 --config-file fc.arm64.json --api-sock firecracker.socketThe user running the above command must be able to use KVM.
Typically this means being part of the kvm group.
Otherwise, run the command above as the root account or prefixed by sudo.
sudo xl create -c xen.x86_64.cfgYou need use sudo or the root account to run Xen.
sudo xl create -c xen.arm64.cfgYou need use sudo or the root account to run Xen.
The shutdown mechanism doesn't currently work with Python3. So the virtual machine is left hanging after printing the Hello message. Closing the virtual machine depends on the platform.
To close the QEMU virtual machine, use the Ctrl+a x keyboard shortcut;
that is press the Ctrl and a keys at the same time and then, separately, press the x key.
To close the Firecracker virtual machine, open another console and use the command:
sudo pkill -f firecrackerTo close the Xen virtual machine, open another console and use the command:
sudo xl destroy python3-helloThe current program is hello.py, a simple Hello-printing Python3 program.
In order to use another program, potentially comprising of multiple source code files, do the following:
-
Create the corresponding Python3 source code files. Ideally, test them locally.
-
Update the
COPYcommand in theDockerfileto copy all source code files. -
Update the command line arguments for starting the virtual machine, to use the new command line arguments instead of
-- /app/hello.py. For QEMU this means updating theqemu-system-x86_64orqemu-system-aarch64command line. For Firecracker this means updating thefc.x86_64.jsonor thefc.arm64.jsonfile. For Xen this means updating thexen.x86_64.cfgor thexen.arm64.cfgfile.
Based on the Dockerfile, the application uses a filesystem for version 3.10.11 of Python.
This is because the Python interpreter build is for 3.10.11, as seen in the Makefile.uk for unikraft/lib-python3.
You can use another filesystem for another Python version, while still using the Python interpreter build for 3.10.11.
For example, to use the filesystem for Python 3.12.7, do the following:
-
Update the
Dockerfileto useFROM python:3.12.7 .... -
Update the
COPY --from=baseline in theDockerfileto usepython3.12instead ofpython3.10. -
Update the command line arguments for starting the virtual machine, to use an updated value for the
PYTHONPATHenvironment variable. As above, usepython3.12instead ofpython3.10.
You can use 9pfs as an alternate filesystem to initrd.
Note that 9pfs does not work with Firecracker.
And it requires re-building Xen to add 9pfs support.
Below find instructions on running Python3 Hello on QEMU with 9pfs support.
You need to use these contents for the Config.uk configuration file:
config APPPYTHON3
bool "Configure Python3 Hello application with initrd as rootfs"
default y
select LIBPYTHON3
select LIBPYTHON3_MAIN_FUNCTION
select LIBVFSCORE
select LIBVFSCORE_AUTOMOUNT_UP
select LIBUK9P
select LIB9PFS
select LIBPOSIX_ENVIRON
select LIBPOSIX_ENVIRON_LIBPARAM
This means you replace these two lines in Config.uk:
select LIBRAMFS
select LIBUKCPIO
with these lines:
select LIBUK9P
select LIB9PFS
Now go through the configure and build steps.
Finally, after configuring networking, use the commands below to run Python3 Hello on QEMU/x86_64 with 9pfs support:
# Create a copy of the filesystem to be mounted as 9pfs.
rm -fr ./9pfs-rootfs
cp -r ./rootfs ./9pfs-rootfs
qemu-system-x86_64 \
-nographic \
-m 256 \
-cpu max \
-fsdev local,id=myid,path=$(pwd)/9pfs-rootfs/,security_model=none \
-device virtio-9p-pci,fsdev=myid,mount_tag=fs0 \
-append "python3-hello_qemu-x86_64 vfs.fstab=[ \"fs0:/:9pfs:::\" ] env.vars=[ PYTHONPATH=\"/usr/local/lib/python3.10:/usr/local/lib/python3.10/site-packages\" ] -- /app/hello.py" \
-kernel out/python3-hello_qemu-x86_64You would use a similar command for QEMU/ARM64.