Incorrect symlink checking => Your python3 install is corrupted.

Bug #1953135 reported by Nico Schlömer
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
ubuntu-release-upgrader (Ubuntu)
Fix Released
Medium
Brian Murray
Jammy
Fix Released
Medium
Brian Murray

Bug Description

This is related to https://bugs.launchpad.net/bugs/1825655.

When trying to upgrade to jammy, I got
```
Your python3 install is corrupted. Please fix the '/usr/bin/python3'
symlink.
```

Digging into the matter, it comes down to this symlink checker in `DistUpgradeController.py`:
```
import logging
from configparser import ConfigParser
import os
from configparser import NoOptionError

logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)

def _pythonSymlinkCheck():
    """ sanity check that /usr/bin/python3 points to the default
        python version. Users tend to modify this symlink, which
        breaks stuff in obscure ways (Ubuntu #75557).
    """
    logging.debug("_pythonSymlinkCheck run")
    binaries_and_dirnames = [("python3", "python3")]
    for binary, dirname in binaries_and_dirnames:
        debian_defaults = '/usr/share/%s/debian_defaults' % dirname
        if os.path.exists(debian_defaults):
            config = ConfigParser()
            with open(debian_defaults) as f:
                config.read_file(f)
            try:
                expected_default = config.get('DEFAULT', 'default-version')
            except NoOptionError:
                logging.debug("no default version for %s found in '%s'" %
                              (binary, config))
                return False
            try:
                fs_default_version = os.readlink('/usr/bin/%s' % binary)
            except OSError as e:
                logging.error("os.readlink failed (%s)" % e)
                return False
            if not fs_default_version in (expected_default, os.path.join('/usr/bin', expected_default)):
                logging.debug("%s symlink points to: '%s', but expected is '%s' or '%s'" %
                              (binary, fs_default_version, expected_default, os.path.join('/usr/bin', expected_default)))
                return False
    return True

res = _pythonSymlinkCheck()
print(res)
```
Running it indeed returns `False` on my machine. The log gives the reason:
```
DEBUG:root:_pythonSymlinkCheck run
DEBUG:root:python3 symlink points to: '/etc/alternatives/python3', but expected is 'python3.9' or '/usr/bin/python3.9'
```
The symlink is not followed through.

Instead of `os.readlink`, you want to use `os.path.realpath`.

tags: added: rls-jj-incoming
Changed in ubuntu-release-upgrader (Ubuntu):
status: New → In Progress
assignee: nobody → Brian Murray (brian-murray)
importance: Undecided → Medium
tags: removed: rls-jj-incoming
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package ubuntu-release-upgrader - 1:22.04.3

---------------
ubuntu-release-upgrader (1:22.04.3) jammy; urgency=medium

  * DistUpgrade/DistUpgradeController.py: switch from using os.readlink to
    os.path.realpath when checking for the default python version. Thanks to
    Nico Schlömer. (LP: #1953135)
  * data/release-upgrades: set Prompt to lts as jammy is an LTS release.
    (LP: #1955843)

 -- Brian Murray <email address hidden> Wed, 05 Jan 2022 14:27:07 -0800

Changed in ubuntu-release-upgrader (Ubuntu Jammy):
status: In Progress → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.