Configuring Remote Python Debugging in VSCode - uyuni-project/uyuni GitHub Wiki

This document expects you have a provisioned Uyuni or MLM containerized server. If you do not, see for example Sumaform.

To set up remote debugging in VSCode for Python parts of Uyuni:

  • Expose debug port for the server container.
  • Install debugpy in the server container.
  • Configure file mapping in VSCode.
  • Modify the Python script we want to debug.

[!IMPORTANT] In this document, we are modifying the Uyuni server container's ephemeral filesystem layer. Reprovisioning/restarting the container undoes the modifications.

Expose Container Debug Port

Use the port 5678 for establishing remote connections to the container. By default, the container does not expose such port. To expose the port, modify the /etc/systemd/system/uyuni-server.service file:

# Make file writable
chmod +w /etc/systemd/system/uyuni-server.service
# Open the file, e.g. in vim
vim /etc/systemd/system/uyuni-server.service

When editing the file, add the 5678:5678 port:

...file omitted...
        -p [::]:8002:8002 \
        -p 5678:5678 \
        -v var-cobbler:/var/lib/cobbler
...file omitted...

Save the file, then restart the Uyuni server:

systemctl daemon-reload
systemctl restart uyuni-server.service

You can verify that the port is now exposed:

podman ps | grep 5678

Installing Debugpy

First, ssh to your server and execute mgrctl term to gain access to the container.

The easiest way to install debugpy is to use zypper:

zypper in python3-debugpy

However, frequently, this is not possible, e.g. the server container has no access to external repositories that have the python3-debugpy package. In that case, we can use pip in a virtual environment to install debugpy:

# Create a new virtual environment
python3 -m venv venv
# Install debugpy into the venv
venv/bin/pip install debugpy
# Move the debugpy from the venv into the system's site packages
cp -r venv/lib/python3.6/site-packages/debugpy* /usr/lib/python3.6/site-packages/
# Verify you can import debugpy from python
python3 -c 'import debugpy' && echo "success"

[!IMPORTANT] If you are debugging the Salt Bundle, you can use pip directly from the bundle. For example, /usr/lib/venv-salt-minion/bin/pip install debugpy. After that, you can verify the debugpy import by executing /usr/lib/venv-salt-minion/bin/python3 -c 'import debugpy' && echo "success".

Configuring VSCode

Before you connect to the remote Python code, you must configure path mapping in VSCode.

VSCode must know that, for example, when you clone the uyuni repository and open the python directory in VSCode, i.e. cd uyuni && code python/, then the contents of ${workspaceFolder}/spacewalk (which corresponds to the spacewalk directory) exists on the remote server as /usr/lib/python3.6/site-packages/spacewalk.

Note that:

  • Without correct path mapping, VSCode will not be able to pause remote script execution.
  • The local and remote file contents must be identical. Otherwise, VSCode might not be able to pause remote script execution, or it will show different lines from the lines that are actually executed remotely.

To configure the path mapping in VSCode, open the python directory in VSCode:

git clone https://github.com/uyuni-project/uyuni.git
cd uyuni
code python/

[!NOTE] If you open the whole Uyuni project in VSCode, for example code uyuni, the following path mapping is incorrect. In such case, you must adapt the path mapping.

Then, press ctrl+shift+d, click create a launch.json file -> python debugger -> remote attach. Enter the hostname or IP address of the host machine that runs the server container, and select port 5678.

In the launch.json file, add "justMyCode": false,. Failure to do so will prevent VSCode from pausing the remote execution.

Then, add the path mapping of files you want to debug. For example, consider want to debug the reposync.py file.

In the container, this file exists in the /usr/lib/python3.6/site-packages/spacewalk/satellite_tools/reposync.py location. This reveals that we need to map the remote /usr/lib/python3.6/site-packages/spacewalk directory to the local ${workspaceFolder}/spacewalk directory.

The full JSON file might look as such:

{
    "version": "0.2.0",
    "configurations": [

        {
            "name": "Python Debugger: Remote Attach",
            "type": "debugpy",
            "request": "attach",
            "connect": {
                "host": "192.127.5.5",
                "port": 5678
            },
            "justMyCode": false,
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}/spacewalk",
                    "remoteRoot": "/usr/lib/python3.6/site-packages/spacewalk"
                }
            ]
        }
    ]
}

Modifying the remote Python script

Continuing with the assumption that we want to debug reposync.py, in the server container, we must modify the file, for example vim /usr/lib/python3.6/site-packages/spacewalk/satellite_tools/reposync.py.

Then, add the following lines into the script:

# ...file omitted...
# Add debugpy
import debugpy
debugpy.listen(("0.0.0.0", 5678))
debugpy.wait_for_client()
# ...rest of the file...
import base64
import configparser
...

This pauses the execution until you connect your remote VSCode debugger to the local script.

Because you modified the remote file, you must modify the local file (in VSCode) to be identical to the remote file. In VSCode, open reposync.py and add the same code on the same location. You must not add or remove any spaces before or after the added text.

[!NOTE] It might be easier to copy the modified file from the Uyuni server into your local development environment.

Finally, add a debug point in VSCode where you want the execution to stop, for example note the red dot on line 629:

image

Script execution

In the case of reposync.py, we can execute the file by using the spacewalk-repo-sync command, for example:

/usr/bin/spacewalk-repo-sync --channel sl-micro-6.1-pool-x86_64 --type yum --non-interactive

After executing the command, you see no output. This is because the script has paused execution until you connect to it from your VSCode.

In VSCode, press F5 to start the remote execution. If you configured everything correctly, you'll see paused execution in your VSCode:

image