Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating category dbus API for installation phases #5329

Merged
merged 2 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pyanaconda/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,3 +512,12 @@ class DisplayModes(Enum):

# FIPS mode minimum LUKS passphrase length
FIPS_PASSPHRASE_MIN_LENGTH = 8


# Installation categories
CATEGORY_UNDEFINED = "UNDEFINED"
CATEGORY_ENVIRONMENT = "ENVIRONMENT_CONFIGURATION"
CATEGORY_STORAGE = "STORAGE_CONFIGURATION"
CATEGORY_SOFTWARE = "SOFTWARE_INSTALLATION"
CATEGORY_BOOTLOADER = "BOOTLOADER_INSTALLATION"
CATEGORY_SYSTEM = "SYSTEM_CONFIGURATION"
65 changes: 45 additions & 20 deletions pyanaconda/installation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
#
from pyanaconda.core.dbus import DBus
from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.core.constants import PAYLOAD_LIVE_TYPES, PAYLOAD_TYPE_DNF
from pyanaconda.core.constants import PAYLOAD_LIVE_TYPES, PAYLOAD_TYPE_DNF, CATEGORY_SYSTEM, \
CATEGORY_BOOTLOADER, CATEGORY_ENVIRONMENT, CATEGORY_STORAGE, CATEGORY_SOFTWARE
from pyanaconda.modules.boss.install_manager.installation_category_interface \
import CategoryReportTaskInterface
from pyanaconda.modules.common.constants.objects import BOOTLOADER, SNAPSHOT, FIREWALL
from pyanaconda.modules.common.constants.services import STORAGE, USERS, SERVICES, NETWORK, \
SECURITY, LOCALIZATION, TIMEZONE, BOSS, SUBSCRIPTION
Expand Down Expand Up @@ -50,7 +53,6 @@ def _writeKS(ksdata):
f.write("# Generated by Anaconda {}\n".format(util.get_anaconda_version_string()))
f.write(str(ksdata))


class RunInstallationTask(InstallationTask):
"""Task to run the installation queue."""

Expand Down Expand Up @@ -82,8 +84,13 @@ def run(self):
ksdata=self._ksdata,
)

def for_publication(self):
"""Return a DBus representation."""
return CategoryReportTaskInterface(self)

def _queue_started_cb(self, task):
"""The installation queue was started."""
self.report_category(task.task_category)
self.report_progress(task.status_message)

def _task_completed_cb(self, task):
Expand All @@ -107,7 +114,8 @@ def _prepare_configuration(self, payload, ksdata):
# we only run the tasks if the Subscription module is available
subscription_config = TaskQueue(
"Subscription configuration",
_("Configuring Red Hat subscription")
_("Configuring Red Hat subscription"),
CATEGORY_SYSTEM
)
subscription_proxy = SUBSCRIPTION.get_proxy()
subscription_dbus_tasks = subscription_proxy.InstallWithTasks()
Expand All @@ -117,7 +125,8 @@ def _prepare_configuration(self, payload, ksdata):
# schedule the execute methods of ksdata that require an installed system to be present
os_config = TaskQueue(
"Installed system configuration",
_("Configuring installed system")
_("Configuring installed system"),
CATEGORY_SYSTEM
)

# add installation tasks for the Security DBus module
Expand Down Expand Up @@ -158,7 +167,8 @@ def _prepare_configuration(self, payload, ksdata):
overwrite = payload.type in PAYLOAD_LIVE_TYPES
network_config = TaskQueue(
"Network configuration",
_("Writing network configuration")
_("Writing network configuration"),
CATEGORY_SYSTEM
)
network_config.append(Task(
"Network configuration",
Expand All @@ -171,7 +181,8 @@ def _prepare_configuration(self, payload, ksdata):
if is_module_available(USERS):
user_config = TaskQueue(
"User creation",
_("Creating users")
_("Creating users"),
CATEGORY_SYSTEM
)
users_proxy = USERS.get_proxy()
users_dbus_tasks = users_proxy.InstallWithTasks()
Expand All @@ -181,7 +192,8 @@ def _prepare_configuration(self, payload, ksdata):
# Anaconda addon configuration
addon_config = TaskQueue(
"Anaconda addon configuration",
_("Configuring addons")
_("Configuring addons"),
CATEGORY_SYSTEM
)

boss_proxy = BOSS.get_proxy()
Expand All @@ -194,7 +206,8 @@ def _prepare_configuration(self, payload, ksdata):
# Initramfs generation
generate_initramfs = TaskQueue(
"Initramfs generation",
_("Generating initramfs")
_("Generating initramfs"),
CATEGORY_BOOTLOADER
)
bootloader_proxy = STORAGE.get_proxy(BOOTLOADER)

Expand Down Expand Up @@ -236,7 +249,8 @@ def run_generate_initramfs():
if flags.flags.kexec:
kexec_setup = TaskQueue(
"Kexec setup",
_("Setting up kexec")
_("Setting up kexec"),
CATEGORY_BOOTLOADER
)
kexec_setup.append(Task(
"Setup kexec",
Expand All @@ -247,7 +261,8 @@ def run_generate_initramfs():
# write anaconda related configs & kickstarts
write_configs = TaskQueue(
"Write configs and kickstarts",
_("Storing configuration files and kickstarts")
_("Storing configuration files and kickstarts"),
CATEGORY_SYSTEM
)

# Write the kickstart file to the installed system (or, copy the input
Expand All @@ -267,7 +282,8 @@ def run_generate_initramfs():

post_scripts = TaskQueue(
"Post installation scripts",
_("Running post-installation scripts")
_("Running post-installation scripts"),
CATEGORY_SYSTEM
)
post_scripts.append(Task(
"Run post installation scripts",
Expand Down Expand Up @@ -315,7 +331,8 @@ def _prepare_installation(self, payload, ksdata):
# setup the installation environment
setup_environment = TaskQueue(
"Installation environment setup",
_("Setting up the installation environment")
_("Setting up the installation environment"),
CATEGORY_ENVIRONMENT
)

boss_proxy = BOSS.get_proxy()
Expand All @@ -341,7 +358,8 @@ def _prepare_installation(self, payload, ksdata):
storage_proxy = STORAGE.get_proxy()
early_storage = TaskQueue(
"Early storage configuration",
_("Configuring storage")
_("Configuring storage"),
CATEGORY_STORAGE
)
early_storage.append_dbus_tasks(STORAGE, storage_proxy.InstallWithTasks())

Expand All @@ -354,7 +372,8 @@ def _prepare_installation(self, payload, ksdata):
# Run %pre-install scripts with the filesystem mounted and no packages
pre_install_scripts = TaskQueue(
"Pre-install scripts",
_("Running pre-installation scripts")
_("Running pre-installation scripts"),
CATEGORY_ENVIRONMENT
)
pre_install_scripts.append(Task(
"Run %pre-install scripts",
Expand All @@ -367,7 +386,8 @@ def _prepare_installation(self, payload, ksdata):
# - check for possibly needed additional packages.
pre_install = TaskQueue(
"Pre install tasks",
_("Running pre-installation tasks")
_("Running pre-installation tasks"),
CATEGORY_SOFTWARE
)

if is_module_available(SECURITY):
Expand All @@ -391,7 +411,8 @@ def _prepare_installation(self, payload, ksdata):

payload_install = TaskQueue(
"Payload installation",
_("Installing the software")
_("Installing the software"),
CATEGORY_SOFTWARE
)
payload_install.append(Task(
"Install the payload",
Expand All @@ -403,7 +424,8 @@ def _prepare_installation(self, payload, ksdata):
if payload.type != PAYLOAD_TYPE_DNF:
late_storage = TaskQueue(
"Late storage configuration",
_("Configuring storage")
_("Configuring storage"),
CATEGORY_STORAGE,
)
conf_task = storage_proxy.WriteConfigurationWithTask()
late_storage.append_dbus_tasks(STORAGE, [conf_task])
Expand All @@ -413,7 +435,8 @@ def _prepare_installation(self, payload, ksdata):
bootloader_proxy = STORAGE.get_proxy(BOOTLOADER)
bootloader_install = TaskQueue(
"Bootloader installation",
_("Installing boot loader")
_("Installing boot loader"),
CATEGORY_BOOTLOADER
)

def run_configure_bootloader():
Expand Down Expand Up @@ -446,7 +469,8 @@ def run_install_bootloader():

post_install = TaskQueue(
"Post-installation setup tasks",
_("Performing post-installation setup tasks")
_("Performing post-installation setup tasks"),
CATEGORY_SYSTEM
)
post_install.append(Task(
"Run post-installation setup tasks",
Expand All @@ -460,7 +484,8 @@ def run_install_bootloader():
if snapshot_proxy.IsRequested(SNAPSHOT_WHEN_POST_INSTALL):
snapshot_creation = TaskQueue(
"Creating post installation snapshots",
_("Creating snapshots")
_("Creating snapshots"),
CATEGORY_STORAGE
)
snapshot_task = snapshot_proxy.CreateWithTask(SNAPSHOT_WHEN_POST_INSTALL)
snapshot_creation.append_dbus_tasks(STORAGE, [snapshot_task])
Expand Down
17 changes: 16 additions & 1 deletion pyanaconda/installation_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ class TaskQueue(BaseTask):
TaskQueues and Tasks can be mixed in a single TaskQueue.
"""

def __init__(self, name, status_message=None):
def __init__(self, name, status_message=None, task_category=None):
super().__init__(name)
self._task_category = task_category
self._status_message = status_message
# the list backing this TaskQueue instance
self._queue = []
Expand All @@ -103,6 +104,20 @@ def __init__(self, name, status_message=None):
self.task_started = Signal()
self.task_completed = Signal()

@property
def task_category(self):
"""A category describing the Queue is trying to achieve.

Eq. "Converting all foo into bar."

The current main usecase is to set the ProgressHub status message when
a TaskQueue is started.

:returns: a task category
:rtype: str
"""
return self._task_category

@property
def status_message(self):
"""A status message describing the Queue is trying to achieve.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# DBus installation task category interface.
#
# API specification of task category interface.
#
# Copyright (C) 2017 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
from dasbus.server.interface import dbus_interface, dbus_signal
from pyanaconda.modules.common.constants.interfaces import TASK_CATEGORY
from dasbus.typing import * # pylint: disable=wildcard-import
from pyanaconda.modules.common.task import TaskInterface

__all__ = ['CategoryReportTaskInterface']


@dbus_interface(TASK_CATEGORY.interface_name)
class CategoryReportTaskInterface(TaskInterface):
"DBus interface for a task category report"

def connect_signals(self):
super().connect_signals()
self.implementation.category_changed_signal.connect(self.CategoryChanged)

@dbus_signal
def CategoryChanged(self, category: Str):
"""Signal making progress for this task.

:param category: Number of the category. See pyanaconda/core/constants.py
InstallationCategories for info about a category indexes.
"""
pass
5 changes: 5 additions & 0 deletions pyanaconda/modules/common/constants/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
basename="Task"
)

TASK_CATEGORY = DBusInterfaceIdentifier(
namespace=ANACONDA_NAMESPACE,
basename="TaskCategory"
)

DEVICE_TREE_VIEWER = DBusInterfaceIdentifier(
namespace=DEVICE_TREE_NAMESPACE,
basename="Viewer"
Expand Down
15 changes: 15 additions & 0 deletions pyanaconda/modules/common/task/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ class ProgressReporter(ABC):
def __init__(self):
super().__init__()
self._progress_changed_signal = Signal()
self._category_changed_signal = Signal()

self.__progress_lock = Lock()
self.__progress_step = 0
self.__progress_category = None
self.__progress_msg = ""

@property
Expand All @@ -55,6 +57,19 @@ def progress_changed_signal(self):
"""Signal emits when the progress of the task changes."""
return self._progress_changed_signal

@property
def category_changed_signal(self):
"""Signal emits when the category of the task changes."""
return self._category_changed_signal

@async_action_nowait
def report_category(self, category):
if category is None:
return
else:
self._category_changed_signal.emit(category)


@async_action_nowait
def report_progress(self, message, step_number=None, step_size=None):
"""Report a progress change.
Expand Down
Loading
Loading