Skip to content

Commit

Permalink
Adds checks for container and bootc hosts
Browse files Browse the repository at this point in the history
  • Loading branch information
jmarrero committed Jul 16, 2024
1 parent 2beb3ef commit 218364d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 18 deletions.
2 changes: 1 addition & 1 deletion dnf/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def do_transaction(self, display=()):
elif 'test' in self.conf.tsflags:
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
if dnf.util.is_container():
if dnf.util.is_bootc_host():
_container_msg = _("""
*** This system is managed with ostree. Changes to the system
*** made with dnf will be lost with the next ostree-based update.
Expand Down
56 changes: 39 additions & 17 deletions dnf/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,29 +644,51 @@ def _is_file_pattern_present(specs):


def is_container():
"""Returns true if DNF is running in a container,
false otherwise.
"""
# This attempts to reimplement
# https://github.com/ostreedev/ostree-rs-ext/blob/b0d1c1e4748c8708149bb6c92998da623260c4c6/lib/src/container_utils.rs#L20
# in python.
container_env_var = 'container'
container_env_file = '/run/.containerenv'
docker_env_file = '/.dockerenv'
# https://stackoverflow.com/questions/20010199/how-to-determine-if-a-process-runs-inside-lxc-docker
if os.getenv(container_env_var) is not None or os.path.isfile(docker_env_file) or os.path.isfile(container_env_file):
return True
else:
return False

def is_bootc_host():
"""Returns true is the system is managed as an immutable container,
false otherwise. If msg is True, a warning message is displayed
for the user.
"""

bootc = '/usr/bin/bootc'
ostree = '/sysroot/ostree'

if os.path.isfile(bootc) and os.access(bootc, os.X_OK):
p = subprocess.Popen([bootc, "status", "--json"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = p.communicate()

if p.returncode == 0:
# check the output of 'bootc status'
j = json.loads(out)
ostree_booted = '/run/ostree-booted'
usr = '/usr/'

# XXX: the API from bootc status is evolving
status = j.get("status", "")
kind = j.get("kind", "")
# Check if usr is writtable and we are in a running ostree system.
# We want this code to return true only when the system is in locked state. If someone ran
# bootc overlay or ostree admin unlock we would want normal DNF path to be ran as it will be
# temporary changes (until reboot).
if os.path.isfile(ostree_booted) and not os.access(usr, os.X_OK):
return True
else:
return False

if kind.lower() == "bootchost" and bool(status.get("isContainer", None)):
return True
elif os.path.isdir(ostree):
def is_bootc_container():
"""Returns true if DNF is running inside a bootc container,
false otherwise. If True, some packages like kernel might be
installed with that in mind. For example only one kernel is
supported on bootc containers and hosts.
## TODO this is not complete right now as it just checks for
/ostree/ to exists. Also not in use. ##
"""
sysroot_ostree = '/sysroot/ostree'
systemd_env_var = 'INVOCATION_ID'
if is_container() and os.path.exists(sysroot_ostree) and not is_bootc_host() and os.getenv(systemd_env_var) is None:
return True
else:
return False

return False

0 comments on commit 218364d

Please sign in to comment.