diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py index c14f836398..83b1900260 100644 --- a/dnf/cli/cli.py +++ b/dnf/cli/cli.py @@ -214,13 +214,12 @@ 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(): - _container_msg = _(""" -*** This system is managed with ostree. Changes to the system -*** made with dnf will be lost with the next ostree-based update. -*** If you do not want to lose these changes, use 'rpm-ostree'. + if dnf.util._is_bootc_host(): + _bootc_host_msg = _(""" +*** Error: system is configured to be read-only; for more +*** information run `bootc status` or `ostree admin status`. """) - logger.info(_container_msg) + logger.info(_bootc_host_msg) raise CliError(_("Operation aborted.")) if self._promptWanted(): diff --git a/dnf/util.py b/dnf/util.py index 1b465bda59..0327321caf 100644 --- a/dnf/util.py +++ b/dnf/util.py @@ -33,13 +33,11 @@ import functools import hawkey import itertools -import json import locale import logging import os import pwd import shutil -import subprocess import sys import tempfile import time @@ -643,30 +641,16 @@ def _is_file_pattern_present(specs): return False -def is_container(): +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. """ + ostree_booted = '/run/ostree-booted' + usr = '/usr/' + # 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). + return os.path.isfile(ostree_booted) and not os.access(usr, os.W_OK) - 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) - - # XXX: the API from bootc status is evolving - status = j.get("status", "") - kind = j.get("kind", "") - - if kind.lower() == "bootchost" and bool(status.get("isContainer", None)): - return True - elif os.path.isdir(ostree): - return True - - return False