feat: feat: Ungroup systemd units in services-systemd module

This commit is contained in:
shivanandvp 2022-07-05 23:08:43 -05:00
parent 8f3ac6e00b
commit 781ced1a59
No known key found for this signature in database
GPG Key ID: 90465D24C5B3C731
3 changed files with 70 additions and 135 deletions

View File

@ -7,10 +7,10 @@
# SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
# SPDX-FileCopyrightText: 2017 Alf Gaida <agaida@siduction.org>
# SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot <groot@kde.org>
# SPDX-FileCopyrightText: 2022 shivanandvp <shivanandvp@rebornos.org>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Calamares is Free Software: see the License-Identifier above.
#
import libcalamares
@ -23,96 +23,61 @@ _ = gettext.translation("calamares-python",
def pretty_name():
return _("Configure systemd services")
return _("Configure systemd units")
def systemctl(targets, command, suffix):
def systemctl(units):
"""
For each entry in @p targets, run "systemctl <command> <thing>",
where <thing> is the entry's name plus the given @p suffix.
(No dot is added between name and suffix; suffix may be empty)
For each entry in @p units, run "systemctl <action> <name>",
where each unit is a map of unit name, action, and a flag.
Returns a failure message, or None if this was successful.
Services that are not mandatory have their failures suppressed
Units that are not mandatory have their failures suppressed
silently.
"""
for svc in targets:
if isinstance(svc, str):
name = svc
for unit in units:
if isinstance(unit, str):
name = unit
action = "enable"
mandatory = False
else:
name = svc["name"]
mandatory = svc.get("mandatory", False)
name = unit["name"]
action = unit.get("action", "enable")
mandatory = unit.get("mandatory", False)
ec = libcalamares.utils.target_env_call(
['systemctl', command, "{}{}".format(name, suffix)]
exit_code = libcalamares.utils.target_env_call(
['systemctl', action, name]
)
if exit_code != 0:
libcalamares.utils.warning(
"Cannot {} systemd unit {}".format(action, name)
)
if ec != 0:
libcalamares.utils.warning(
"Cannot {} systemd {} {}".format(command, suffix, name)
)
libcalamares.utils.warning(
"systemctl {} call in chroot returned error code {}".format(command, ec)
)
"systemctl {} call in chroot returned error code {}".format(action, exit_code)
)
if mandatory:
title = _("Cannot modify service")
diagnostic = _("<code>systemctl {arg!s}</code> call in chroot returned error code {num!s}.").format(arg=command, num=ec)
if command == "enable" and suffix == ".service":
description = _("Cannot enable systemd service <code>{name!s}</code>.")
elif command == "enable" and suffix == ".target":
description = _("Cannot enable systemd target <code>{name!s}</code>.")
elif command == "enable" and suffix == ".timer":
description = _("Cannot enable systemd timer <code>{name!s}</code>.")
elif command == "disable" and suffix == ".service":
description = _("Cannot enable systemd service <code>{name!s}</code>.")
elif command == "disable" and suffix == ".target":
description = _("Cannot disable systemd target <code>{name!s}</code>.")
elif command == "mask":
description = _("Cannot mask systemd unit <code>{name!s}</code>.")
else:
description = _("Unknown systemd commands <code>{command!s}</code> and <code>{suffix!s}</code> for unit {name!s}.")
return (title,
description.format(name=name, command=command, suffix=suffix) + " " + diagnostic
)
title = _("Cannot modify unit")
diagnostic = _("<code>systemctl {_action!s}</code> call in chroot returned error code {_exit_code!s}.").format(_action=action, _exit_code=exit_code)
description = _("Cannot {_action!s} systemd unit <code>{_name!s}</code>.").format(_action=action, _name=name)
return (
title,
description + " " + diagnostic
)
return None
def run():
"""
Setup systemd services
Setup systemd units
"""
cfg = libcalamares.job.configuration
# note that the "systemctl enable" and "systemctl disable" commands used
# here will work in a chroot; in fact, they are the only systemctl commands
# that support that, see:
# http://0pointer.de/blog/projects/changing-roots.html
r = systemctl(cfg.get("services", []), "enable", ".service")
if r is not None:
return r
r = systemctl(cfg.get("targets", []), "enable", ".target")
if r is not None:
return r
r = systemctl(cfg.get("timers", []), "enable", ".timer")
if r is not None:
return r
r = systemctl(cfg.get("disable", []), "disable", ".service")
if r is not None:
return r
r = systemctl(cfg.get("disable-targets", []), "disable", ".target")
if r is not None:
return r
r = systemctl(cfg.get("mask", []), "mask", "")
if r is not None:
return r
return_value = systemctl(
cfg.get("units", [])
)
if return_value is not None:
return return_value
return None

View File

@ -1,79 +1,53 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
# Systemd services manipulation.
# Systemd units manipulation.
#
# This module can enable services, timers and targets for systemd
# (if packaging doesn't already do that). It can also
# disable services and targets as well as mask units.
#
# The order of operations is fixed. Enable services, enable targets,
# enable timers, disable services, disable targets and finally apply masks.
# This module can perform actions using systemd units,
# (for example, enabling, disabling, or masking services, sockets, paths, etc.)
---
# There are several configuration keys for this module:
# *services*, *targets*, *timers*, *disable*, *disable-targets* and *mask*.
# The value of each key is a list of entries. Each entry has two keys:
# - *name* is the (string) name of the service or target that is being
# changed. Use quotes. Don't include unit suffix in the name. For
# example, it should be "NetworkManager", not "NetworkManager.service"
# There is one key for this module: *units*. Its value is a list of entries.
# Each entry has three keys:
# - *name* is the (string) name of the systemd unit that is being changed.
# Use quotes. You can use any valid systemd unit here (for example,
# "NetworkManager.service", "cups.socket", "lightdm", "gdm", etc.)
# - *action* is the (string) action that you want to perform over the unit
# (for example, "enable", "disable", "mask", "unmask", etc.). Please
# ensure that the action can actually run under chroot (otherwise it is
# pointless)
# - *mandatory* is a boolean option, which states whether the change
# must be done successfully. If systemd reports an error while changing
# a mandatory entry, the installation will fail. When mandatory is false,
# errors for that systemd unit are ignored. If mandatory
# is not specified, the default is false.
#
# An entry may also be given as a single string, which is then
# interpreted as the name of the service. In this case, mandatory
# is also set to the default of false.
#
# Use [] to express an empty list.
# The order of operations is the same as the order in which entries
# appear in the list
# # This example enables NetworkManager (and fails if it can't),
# # disables cups (and ignores failure). Then it enables the
# # This example enables NetworkManager.service (and fails if it can't),
# # disables cups.socket (and ignores failure). Then it enables the
# # graphical target (e.g. so that SDDM runs for login), and
# # finally disables pacman-init (an ArchLinux-only service).
# # finally masks pacman-init (an ArchLinux-only service).
# #
# # Enables <name>.service
# services:
# units:
# - name: "NetworkManager"
# action: "enable"
# mandatory: true
# - name: "cups"
#
# - name: "cups.socket"
# action: "disable"
# mandatory: false
#
# # Enables <name>.target
# targets:
# - name: "graphical"
# mandatory: true
# action: "enable"
# # The property "mandatory" is taken to be false by default here
# # because it is not specified
#
# # Enables <name>.timer
# timers:
# - name: "fstrim"
# mandatory: false
#
# # Disables <name>.service
# disable:
# - name: "pacman-init"
# mandatory: false
#
# # Disables <name>.target
# # .. this shows how to use just the name
# disable-targets:
# - graphical
#
# # Masks (stronger version of disable). This section
# # is unusual because you **must** include the suffix
# # (e.g. ".service") as part of the name, so, e.g. to mask
# # NetworkManager (rather than just disable it) you must
# # specify "NetworkManager.service" as name.
# mask:
# - name: "NetworkManager.service"
# - mandatory: true
# action: "mask"
# # The property "mandatory" is taken to be false by default here
# # because it is not specified
# By default, no changes are made.
services: []
targets: []
timers: []
disable: []
disable-targets: []
mask: []
units: []

View File

@ -4,22 +4,18 @@
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/services-systemd
definitions:
service:
$id: 'definitions/service'
unit:
$id: 'definitions/unit'
type: object
description: a name and a flag for services, targets, and others
description: a map containing a unit name, an action, and whether it is mandatory
additionalProperties: false
properties:
name: { type: string }
action: { type: string, default: "enable" }
mandatory: { type: boolean, default: false }
required: [ name ]
additionalProperties: false
type: object
properties:
services: { type: array, items: { $ref: 'definitions/service' } }
targets: { type: array, items: { $ref: 'definitions/service' } }
timers: { type: array, items: { $ref: 'definitions/service' } }
disable: { type: array, items: { $ref: 'definitions/service' } }
disable-targets: { type: array, items: { $ref: 'definitions/service' } }
mask: { type: array, items: { $ref: 'definitions/service' } }
units: { type: array, items: { $ref: 'definitions/unit' } }