Compare commits
1 Commits
packagecho
...
services-a
Author | SHA1 | Date | |
---|---|---|---|
d6691aea6b |
@@ -1,2 +0,0 @@
|
||||
SPDX-FileCopyrightText: 2020 demmm <anke62@gmail.com>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
@@ -42,7 +42,7 @@ Item {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("OpenRC base system.<br/>
|
||||
text: qsTr("LibreOffice is a powerful and free office suite, used by millions of people around the world. It includes several applications that make it the most versatile Free and Open Source office suite on the market.<br/>
|
||||
Default option.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
@@ -50,14 +50,76 @@ Item {
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element2
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("LibreOffice")
|
||||
checked: true
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 14
|
||||
radius: 10
|
||||
color: element2.checked ? "#3498db" : "#B9B9B9"
|
||||
border.color: element2.checked ? "#3498db" : "#cccccc"
|
||||
|
||||
Rectangle {
|
||||
x: element2.checked ? parent.width - width : 0
|
||||
y: (parent.height - height) / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: element2.down ? "#cccccc" : "#ffffff"
|
||||
border.color: element2.checked ? (element1.down ? "#3498db" : "#3498db") : "#999999"
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "libreoffice"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image2
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/libreoffice.jpg"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 700
|
||||
height: 150
|
||||
radius: 10
|
||||
border.width: 0
|
||||
Text {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("If you don't want to install an office suite, just select No Office Suite. You can always add one (or more) later on your installed system as the need arrives.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element1
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("OpenRC")
|
||||
checked: true
|
||||
text: qsTr("No Office Suite")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
@@ -81,80 +143,18 @@ Item {
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-openrc"
|
||||
config.packageChoice = "no_office_suite"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image1
|
||||
id: image
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 700
|
||||
height: 150
|
||||
radius: 10
|
||||
border.width: 0
|
||||
Text {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Dinit base system.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element2
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("Dinit")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 14
|
||||
radius: 10
|
||||
color: element2.checked ? "#3498db" : "#B9B9B9"
|
||||
border.color: element2.checked ? "#3498db" : "#cccccc"
|
||||
|
||||
Rectangle {
|
||||
x: element2.checked ? parent.width - width : 0
|
||||
y: (parent.height - height) / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: element2.down ? "#cccccc" : "#ffffff"
|
||||
border.color: element2.checked ? (element2.down ? "#3498db" : "#3498db") : "#999999"
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-dinit"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image2
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
source: "images/no-selection.png"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -169,7 +169,7 @@ Item {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Runit base system.")
|
||||
text: qsTr("Create a minimal Desktop install, remove all extra applications and decide later on what you would like to add to your system. Examples of what won't be on such an install, there will be no Office Suite, no media players, no image viewer or print support. It will be just a desktop, file browser, package manager, text editor and simple web-browser.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
@@ -182,7 +182,7 @@ Item {
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("Runit")
|
||||
text: qsTr("Minimal Install")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
@@ -207,7 +207,7 @@ Item {
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-runit"
|
||||
config.packageChoice = "minimal_install"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,70 +218,7 @@ Item {
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 700
|
||||
height: 150
|
||||
color: "#ffffff"
|
||||
radius: 10
|
||||
border.width: 0
|
||||
Text {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("S6 base system.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element4
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("S6")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 14
|
||||
radius: 10
|
||||
color: element4.checked ? "#3498db" : "#B9B9B9"
|
||||
border.color: element4.checked ? "#3498db" : "#cccccc"
|
||||
|
||||
Rectangle {
|
||||
x: element4.checked ? parent.width - width : 0
|
||||
y: (parent.height - height) / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: element4.down ? "#cccccc" : "#ffffff"
|
||||
border.color: element4.checked ? (element4.down ? "#3498db" : "#3498db") : "#999999"
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-s6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image4
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
source: "images/plasma.png"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +230,7 @@ Item {
|
||||
Text {
|
||||
height: 25
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Please select an option for your install, or use the default: OpenRC.")
|
||||
text: qsTr("Please select an option for your install, or use the default: LibreOffice included.")
|
||||
font.pointSize: 10
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
@@ -4,6 +4,5 @@
|
||||
<file>images/libreoffice.jpg</file>
|
||||
<file>images/no-selection.png</file>
|
||||
<file>images/plasma.png</file>
|
||||
<file>images/artix.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -42,7 +42,7 @@ Item {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("OpenRC base system.<br/>
|
||||
text: qsTr("LibreOffice is a powerful and free office suite, used by millions of people around the world. It includes several applications that make it the most versatile Free and Open Source office suite on the market.<br/>
|
||||
Default option.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
@@ -50,14 +50,76 @@ Item {
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element2
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("LibreOffice")
|
||||
checked: true
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 14
|
||||
radius: 10
|
||||
color: element2.checked ? "#3498db" : "#B9B9B9"
|
||||
border.color: element2.checked ? "#3498db" : "#cccccc"
|
||||
|
||||
Rectangle {
|
||||
x: element2.checked ? parent.width - width : 0
|
||||
y: (parent.height - height) / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: element2.down ? "#cccccc" : "#ffffff"
|
||||
border.color: element2.checked ? (element1.down ? "#3498db" : "#3498db") : "#999999"
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "libreoffice"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image2
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/libreoffice.jpg"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 700
|
||||
height: 150
|
||||
radius: 10
|
||||
border.width: 0
|
||||
Text {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("If you don't want to install an office suite, just select No Office Suite. You can always add one (or more) later on your installed system as the need arrives.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element1
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("OpenRC")
|
||||
checked: true
|
||||
text: qsTr("No Office Suite")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
@@ -81,80 +143,18 @@ Item {
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-openrc"
|
||||
config.packageChoice = "no_office_suite"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image1
|
||||
id: image
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 700
|
||||
height: 150
|
||||
radius: 10
|
||||
border.width: 0
|
||||
Text {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Dinit base system.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element2
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("Dinit")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 14
|
||||
radius: 10
|
||||
color: element2.checked ? "#3498db" : "#B9B9B9"
|
||||
border.color: element2.checked ? "#3498db" : "#cccccc"
|
||||
|
||||
Rectangle {
|
||||
x: element2.checked ? parent.width - width : 0
|
||||
y: (parent.height - height) / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: element2.down ? "#cccccc" : "#ffffff"
|
||||
border.color: element2.checked ? (element2.down ? "#3498db" : "#3498db") : "#999999"
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-dinit"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image2
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
source: "images/no-selection.png"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -169,7 +169,7 @@ Item {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Runit base system.")
|
||||
text: qsTr("Create a minimal Desktop install, remove all extra applications and decide later on what you would like to add to your system. Examples of what won't be on such an install, there will be no Office Suite, no media players, no image viewer or print support. It will be just a desktop, file browser, package manager, text editor and simple web-browser.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
@@ -182,7 +182,7 @@ Item {
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("Runit")
|
||||
text: qsTr("Minimal Install")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
@@ -207,7 +207,7 @@ Item {
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-runit"
|
||||
config.packageChoice = "minimal_install"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,70 +218,7 @@ Item {
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 700
|
||||
height: 150
|
||||
color: "#ffffff"
|
||||
radius: 10
|
||||
border.width: 0
|
||||
Text {
|
||||
width: 450
|
||||
height: 104
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("S6 base system.")
|
||||
font.pointSize: 10
|
||||
anchors.verticalCenterOffset: -10
|
||||
anchors.horizontalCenterOffset: 100
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Switch {
|
||||
id: element4
|
||||
x: 500
|
||||
y: 110
|
||||
width: 187
|
||||
height: 14
|
||||
text: qsTr("S6")
|
||||
checked: false
|
||||
hoverEnabled: true
|
||||
ButtonGroup.group: switchGroup
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 40
|
||||
implicitHeight: 14
|
||||
radius: 10
|
||||
color: element4.checked ? "#3498db" : "#B9B9B9"
|
||||
border.color: element4.checked ? "#3498db" : "#cccccc"
|
||||
|
||||
Rectangle {
|
||||
x: element4.checked ? parent.width - width : 0
|
||||
y: (parent.height - height) / 2
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 10
|
||||
color: element4.down ? "#cccccc" : "#ffffff"
|
||||
border.color: element4.checked ? (element4.down ? "#3498db" : "#3498db") : "#999999"
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
if ( checked ) {
|
||||
config.packageChoice = "elogind-s6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: image4
|
||||
x: 8
|
||||
y: 25
|
||||
height: 100
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: "images/artix.png"
|
||||
source: "images/plasma.png"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +230,7 @@ Item {
|
||||
Text {
|
||||
height: 25
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Please select an option for your install, or use the default: OpenRC.")
|
||||
text: qsTr("Please select an option for your install, or use the default: LibreOffice included.")
|
||||
font.pointSize: 10
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
@@ -4,6 +4,5 @@
|
||||
<file>images/libreoffice.jpg</file>
|
||||
<file>images/no-selection.png</file>
|
||||
<file>images/plasma.png</file>
|
||||
<file>images/artix.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
419
src/modules/services-artix/main.py
Normal file
419
src/modules/services-artix/main.py
Normal file
@@ -0,0 +1,419 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# === This file is part of Calamares - <https://calamares.io> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2016 Artoo <artoo@manjaro.org>
|
||||
# SPDX-FileCopyrightText: 2017 Philip Müller <philm@manjaro.org>
|
||||
# SPDX-FileCopyrightText: 2018 Artoo <artoo@artixlinux.org>
|
||||
# SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Calamares is Free Software: see the License-Identifier above.
|
||||
#
|
||||
|
||||
import libcalamares
|
||||
|
||||
from libcalamares.utils import target_env_call, warning
|
||||
from os.path import exists, join
|
||||
|
||||
|
||||
import gettext
|
||||
_ = gettext.translation("calamares-python",
|
||||
localedir=libcalamares.utils.gettext_path(),
|
||||
languages=libcalamares.utils.gettext_languages(),
|
||||
fallback=True).gettext
|
||||
|
||||
|
||||
def pretty_name():
|
||||
return _("Configure artix services")
|
||||
|
||||
# TODO: cleran up this merged mess, implement meta class
|
||||
class OpenrcController:
|
||||
"""
|
||||
This is the openrc service controller.
|
||||
All of its state comes from global storage and the job
|
||||
configuration at initialization time.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.root = libcalamares.globalstorage.value('rootMountPoint')
|
||||
|
||||
# Translate the entries in the config to the actions passed to rc-config
|
||||
self.services = dict()
|
||||
self.services["add"] = libcalamares.job.configuration.get('services', [])
|
||||
self.services["del"] = libcalamares.job.configuration.get('disable', [])
|
||||
|
||||
openrc = libcalamares.job.configuration.get('openrc', None)
|
||||
if openrc is None:
|
||||
openrc = dict()
|
||||
if type(openrc) is not dict:
|
||||
libcalamares.utils.warning("Job configuration *openrc* will be ignored.")
|
||||
openrc = dict()
|
||||
|
||||
self.openrc_initdDir = openrc.get('initdDir')
|
||||
self.openrc_runlevelsDir = openrc.get('runlevelsDir')
|
||||
|
||||
|
||||
def make_failure_description(self, state, name, runlevel):
|
||||
"""
|
||||
Returns a generic "could not <foo>" failure message, specialized
|
||||
for the action @p state and the specific service @p name in @p runlevel.
|
||||
"""
|
||||
if state == "add":
|
||||
description = _("Cannot add service {name!s} to run-level {level!s}.")
|
||||
elif state == "del":
|
||||
description = _("Cannot remove service {name!s} from run-level {level!s}.")
|
||||
else:
|
||||
description = _("Unknown service-action <code>{arg!s}</code> for service {name!s} in run-level {level!s}.")
|
||||
|
||||
return description.format(arg=state, name=name, level=runlevel)
|
||||
|
||||
|
||||
def update(self, state):
|
||||
"""
|
||||
Call rc-update for each service listed
|
||||
in services for the given @p state. rc-update
|
||||
is called with @p state as the command as well.
|
||||
"""
|
||||
|
||||
for svc in self.services.get(state, []):
|
||||
if isinstance(svc, str):
|
||||
name = svc
|
||||
runlevel = "default"
|
||||
mandatory = False
|
||||
else:
|
||||
name = svc["name"]
|
||||
runlevel = svc.get("runlevel", "default")
|
||||
mandatory = svc.get("mandatory", False)
|
||||
|
||||
service_path = self.root + self.openrc_initdDir + "/" + name
|
||||
runlevel_path = self.root + self.openrc_runlevelsDir + "/" + runlevel
|
||||
|
||||
if exists(service_path):
|
||||
if exists(runlevel_path):
|
||||
ec = target_env_call(["rc-update", state, name, runlevel])
|
||||
if ec != 0:
|
||||
warning("Cannot {} service {} to {}".format(state, name, runlevel))
|
||||
warning("rc-update returned error code {!s}".format(ec))
|
||||
if mandatory:
|
||||
title = _("Cannot modify service")
|
||||
diagnostic = _("<code>rc-update {arg!s}</code> call in chroot returned error code {num!s}.").format(arg=state, num=ec)
|
||||
return (title,
|
||||
self.make_failure_description(state, name, runlevel) + " " + diagnostic
|
||||
)
|
||||
else:
|
||||
warning("Target runlevel {} does not exist for {}.".format(runlevel, name))
|
||||
if mandatory:
|
||||
title = _("Target runlevel does not exist")
|
||||
diagnostic = _("The path for runlevel {level!s} is <code>{path!s}</code>, which does not exist.").format(level=runlevel, path=runlevel_path)
|
||||
|
||||
return (title,
|
||||
self.make_failure_description(state, name, runlevel) + " " + diagnostic
|
||||
)
|
||||
else:
|
||||
warning("Target service {} does not exist in {}.".format(name, self.openrc_initdDir))
|
||||
if mandatory:
|
||||
title = _("Target service does not exist")
|
||||
diagnostic = _("The path for service {name!s} is <code>{path!s}</code>, which does not exist.").format(name=name, path=service_path)
|
||||
return (title,
|
||||
self.make_failure_description(state, name, runlevel) + " " + diagnostic
|
||||
)
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Run the controller
|
||||
"""
|
||||
|
||||
for state in ("add", "del"):
|
||||
r = self.update(state)
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
class S6Controller:
|
||||
"""
|
||||
This is the s6 service controller.
|
||||
All of its state comes from global storage and the job
|
||||
configuration at initialization time.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.root = libcalamares.globalstorage.value('rootMountPoint')
|
||||
|
||||
s6 = libcalamares.job.configuration.get('s6', None)
|
||||
if s6 is None:
|
||||
s6 = dict()
|
||||
if type(s6) is not dict:
|
||||
libcalamares.utils.warning("Job configuration *s6* will be ignored.")
|
||||
s6 = dict()
|
||||
|
||||
self.s6_dbDir = s6.get('dbDir')
|
||||
self.s6_defaultBundle = s6.get('defaultBundle')
|
||||
|
||||
self.services = dict()
|
||||
self.services["add"] = libcalamares.job.configuration.get('services', [])
|
||||
self.services["delete"] = libcalamares.job.configuration.get('disable', [])
|
||||
|
||||
|
||||
def makeBundle(self):
|
||||
"""
|
||||
Call s6-rc-bundle with each service listed
|
||||
in services as arg.
|
||||
"""
|
||||
|
||||
deleteBundles = self.services.get("delete", [])
|
||||
|
||||
if deleteBundles:
|
||||
ec = target_env_call(["s6-rc-bundle", "-c", self.s6_dbDir, "delete", *deleteBundles])
|
||||
if ec != 0:
|
||||
warning("Cannot delete {}".format(*deleteBundles))
|
||||
warning("s6-rc-bundle returned error code {!s}".format(ec))
|
||||
|
||||
for svc in self.services.get('add', []):
|
||||
ec = target_env_call(["s6-rc-db", "-c", self.s6_dbDir, "type", svc])
|
||||
if ec != 0:
|
||||
warning("Service {} does not exist.".format(svc))
|
||||
warning("s6-rc-db returned error code {!s}".format(ec))
|
||||
else:
|
||||
ec = target_env_call(["s6-service", "add", self.s6_defaultBundle, svc])
|
||||
if ec != 0:
|
||||
warning("Cannot add service {} to {} bundle".format(svc, self.s6_defaultBundle))
|
||||
warning("s6-service returned error code {!s}".format(ec))
|
||||
|
||||
ec = target_env_call(["s6-db-reload", "-r"])
|
||||
if ec != 0:
|
||||
warning("Cannot reload service db.")
|
||||
warning("s6-db-reload returned error code {!s}".format(ec))
|
||||
|
||||
def run(self):
|
||||
"""Run the controller
|
||||
"""
|
||||
|
||||
r = self.makeBundle()
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
class DinitController:
|
||||
"""
|
||||
This is the dinit service controller.
|
||||
All of its state comes from global storage and the job
|
||||
configuration at initialization time.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.root = libcalamares.globalstorage.value('rootMountPoint')
|
||||
|
||||
# Translate the entries in the config to the actions passed to sv-helper
|
||||
self.services = dict()
|
||||
self.services["enable"] = libcalamares.job.configuration.get('services', [])
|
||||
self.services["disable"] = libcalamares.job.configuration.get('disable', [])
|
||||
|
||||
dinit = libcalamares.job.configuration.get('dinit', None)
|
||||
if dinit is None:
|
||||
dinit = dict()
|
||||
if type(dinit) is not dict:
|
||||
libcalamares.utils.warning("Job configuration *dinit* will be ignored.")
|
||||
dinit = dict()
|
||||
|
||||
self.dinit_initdDir = dinit.get('initdDir')
|
||||
self.dinit_runsvDir = dinit.get('runsvDir')
|
||||
|
||||
|
||||
def make_failure_description(self, state, name):
|
||||
"""
|
||||
Returns a generic "could not <foo>" failure message, specialized
|
||||
for the action @p state and the specific service @p name.
|
||||
"""
|
||||
if state == "enable":
|
||||
description = _("Cannot enable service {name!s}.")
|
||||
elif state == "disable":
|
||||
description = _("Cannot disable service {name!s}.")
|
||||
else:
|
||||
description = _("Unknown service-action <code>{arg!s}</code> for service {name!s}.")
|
||||
|
||||
return description.format(arg=state, name=name)
|
||||
|
||||
|
||||
def update(self, state):
|
||||
"""
|
||||
Process each service listed
|
||||
in services for the given @p state.
|
||||
"""
|
||||
|
||||
for svc in self.services.get(state, []):
|
||||
if isinstance(svc, str):
|
||||
name = svc
|
||||
mandatory = False
|
||||
else:
|
||||
name = svc["name"]
|
||||
mandatory = svc.get("mandatory", False)
|
||||
|
||||
service_path = self.root + self.dinit_initdDir + "/" + name
|
||||
runlevel_path = self.root + self.dinit_runsvDir
|
||||
src = self.dinit_initdDir + "/" + name
|
||||
dest = self.dinit_runsvDir + "/"
|
||||
|
||||
if state == 'enable':
|
||||
cmd = ["ln", "-sv", src, dest]
|
||||
elif state == 'disable':
|
||||
cmd = ["rm", "-rv", dest]
|
||||
|
||||
if exists(service_path):
|
||||
if exists(runlevel_path):
|
||||
ec = target_env_call(cmd)
|
||||
if ec != 0:
|
||||
warning("Cannot {} service {}".format(state, name))
|
||||
warning("{} returned error code {!s}".format(cmd, ec))
|
||||
if mandatory:
|
||||
title = _("Cannot modify service")
|
||||
diagnostic = _("<code>cmd {arg!s}</code> call in chroot returned error code {num!s}.").format(arg=state, num=ec)
|
||||
return (title,
|
||||
self.make_failure_description(state, name) + " " + diagnostic
|
||||
)
|
||||
else:
|
||||
warning("Target service {} does not exist in {}.".format(name, self.dinit_initdDir))
|
||||
if mandatory:
|
||||
title = _("Target service does not exist")
|
||||
diagnostic = _("The path for service {name!s} is <code>{path!s}</code>, which does not exist.").format(name=name, path=service_path)
|
||||
return (title,
|
||||
self.make_failure_description(state, name) + " " + diagnostic
|
||||
)
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Run the controller
|
||||
"""
|
||||
|
||||
for state in ("enable", "disable"):
|
||||
r = self.update(state)
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
class RunitController:
|
||||
"""
|
||||
This is the runit service controller.
|
||||
All of its state comes from global storage and the job
|
||||
configuration at initialization time.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.root = libcalamares.globalstorage.value('rootMountPoint')
|
||||
|
||||
# Translate the entries in the config to the actions passed to sv-helper
|
||||
self.services = dict()
|
||||
self.services["enable"] = libcalamares.job.configuration.get('services', [])
|
||||
self.services["disable"] = libcalamares.job.configuration.get('disable', [])
|
||||
|
||||
runit = libcalamares.job.configuration.get('runit', None)
|
||||
if runit is None:
|
||||
runit = dict()
|
||||
if type(runit) is not dict:
|
||||
libcalamares.utils.warning("Job configuration *runit* will be ignored.")
|
||||
runit = dict()
|
||||
|
||||
self.runit_svDir = libcalamares.job.configuration['svDir']
|
||||
self.runit_runsvDir = libcalamares.job.configuration['runsvDir']
|
||||
|
||||
|
||||
def make_failure_description(self, state, name, runlevel):
|
||||
"""
|
||||
Returns a generic "could not <foo>" failure message, specialized
|
||||
for the action @p state and the specific service @p name in @p runlevel.
|
||||
"""
|
||||
if state == "enable":
|
||||
description = _("Cannot enable service {name!s} to run-level {level!s}.")
|
||||
elif state == "disable":
|
||||
description = _("Cannot disable service {name!s} from run-level {level!s}.")
|
||||
else:
|
||||
description = _("Unknown service-action <code>{arg!s}</code> for service {name!s} in run-level {level!s}.")
|
||||
|
||||
return description.format(arg=state, name=name, level=runlevel)
|
||||
|
||||
|
||||
def update(self, state):
|
||||
"""
|
||||
Call sv-helper for each service listed
|
||||
in services for the given @p state.
|
||||
"""
|
||||
|
||||
for svc in self.services.get(state, []):
|
||||
if isinstance(svc, str):
|
||||
name = svc
|
||||
runlevel = "default"
|
||||
mandatory = False
|
||||
else:
|
||||
name = svc["name"]
|
||||
runlevel = svc.get("runlevel", "default")
|
||||
mandatory = svc.get("mandatory", False)
|
||||
|
||||
service_path = self.root + self.runit_svDir + "/" + name
|
||||
runlevel_path = self.root + self.runit_runsvDir + "/" + runlevel
|
||||
src = self.runit_svDir + "/" + name
|
||||
dest = self.runit_runsvDir + "/" + runlevel + "/"
|
||||
|
||||
if state == 'enable':
|
||||
cmd = ["ln", "-sv", src, dest]
|
||||
elif state == 'disable':
|
||||
cmd = ["rm", "-rv", dest]
|
||||
|
||||
if exists(service_path):
|
||||
if exists(runlevel_path):
|
||||
ec = target_env_call(cmd)
|
||||
if ec != 0:
|
||||
warning("Cannot {} service {} to {}".format(state, name, runlevel))
|
||||
warning("{} returned error code {!s}".format(cmd, ec))
|
||||
if mandatory:
|
||||
title = _("Cannot modify service")
|
||||
diagnostic = _("<code>cmd {arg!s}</code> call in chroot returned error code {num!s}.").format(arg=state, num=ec)
|
||||
return (title,
|
||||
self.make_failure_description(state, name, runlevel) + " " + diagnostic
|
||||
)
|
||||
else:
|
||||
warning("Target runlevel {} does not exist for {}.".format(runlevel, name))
|
||||
if mandatory:
|
||||
title = _("Target runlevel does not exist")
|
||||
diagnostic = _("The path for runlevel {level!s} is <code>{path!s}</code>, which does not exist.").format(level=runlevel, path=runlevel_path)
|
||||
|
||||
return (title,
|
||||
self.make_failure_description(state, name, runlevel) + " " + diagnostic
|
||||
)
|
||||
else:
|
||||
warning("Target service {} does not exist in {}.".format(name, self.svDir))
|
||||
if mandatory:
|
||||
title = _("Target service does not exist")
|
||||
diagnostic = _("The path for service {name!s} is <code>{path!s}</code>, which does not exist.").format(name=name, path=service_path)
|
||||
return (title,
|
||||
self.make_failure_description(state, name, runlevel) + " " + diagnostic
|
||||
)
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Run the controller
|
||||
"""
|
||||
|
||||
for state in ("enable", "disable"):
|
||||
r = self.update(state)
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
def run():
|
||||
"""
|
||||
Setup services
|
||||
"""
|
||||
if libcalamares.globalstorage.contains("initProvider"):
|
||||
init_provider = libcalamares.globalstorage.value("initProvider")
|
||||
|
||||
match init_provider:
|
||||
case 'openrc':
|
||||
return OpenrcController().run()
|
||||
case's6':
|
||||
return S6Controller().run()
|
||||
case 'dinit':
|
||||
return DinitController().run()
|
||||
case 'runit':
|
||||
return RunitController().run()
|
||||
case _:
|
||||
return None
|
||||
|
||||
|
||||
|
7
src/modules/services-artix/module.desc
Normal file
7
src/modules/services-artix/module.desc
Normal file
@@ -0,0 +1,7 @@
|
||||
# SPDX-FileCopyrightText: no
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
---
|
||||
type: "job"
|
||||
name: "services-artix"
|
||||
interface: "python"
|
||||
script: "main.py"
|
68
src/modules/services-artix/services-artix.conf
Normal file
68
src/modules/services-artix/services-artix.conf
Normal file
@@ -0,0 +1,68 @@
|
||||
# SPDX-FileCopyrightText: no
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
#
|
||||
# openrc services module to modify service runlevels via rc-update in the chroot
|
||||
#
|
||||
# Services can be added (to any runlevel, or multiple runlevels) or deleted.
|
||||
# Handle del with care and only use it if absolutely necessary.
|
||||
#
|
||||
# if a service is listed in the conf but is not present/detected on the target system,
|
||||
# or a runlevel does not exist, it will be ignored and skipped; a warning is logged.
|
||||
#
|
||||
---
|
||||
|
||||
openrc:
|
||||
# initdDir: holds the openrc service directory location
|
||||
initdDir: /etc/init.d
|
||||
# runlevelsDir: holds the runlevels directory location
|
||||
runlevelsDir: /etc/runlevels
|
||||
|
||||
dinit:
|
||||
# initdDir: holds the runit service directory location
|
||||
initdDir: /etc/dinit.d
|
||||
# runsvDir: holds the runlevels directory location
|
||||
runsvDir: /etc/dinit.d/boot.d
|
||||
|
||||
runit:
|
||||
# svDir: holds the runit service directory location
|
||||
svDir: /etc/runit/sv
|
||||
# runsvDir: holds the runlevels directory location
|
||||
runsvDir: /etc/runit/runsvdir
|
||||
|
||||
s6:
|
||||
# database path
|
||||
dbDir: /etc/s6/rc/compiled
|
||||
# default bundle name
|
||||
defaultBundle: default
|
||||
|
||||
# services: a list of entries to **enable**
|
||||
# disable: a list of entries to **disable**
|
||||
#
|
||||
# Each entry has three fields:
|
||||
# - name: the service name
|
||||
# - (optional) runlevel: can hold any runlevel present on the target
|
||||
# system; if no runlevel is provided, "default" is assumed.
|
||||
# - (optional) mandatory: if set to true, a failure to modify
|
||||
# the service will result in installation failure, rather than just
|
||||
# a warning. The default is false.
|
||||
#
|
||||
# an entry may also be a single string, which is interpreted
|
||||
# as the name field (runlevel "default" is assumed then, and not-mandatory).
|
||||
#
|
||||
# # Example services and disable settings:
|
||||
# # - add foo1 to default, but it must succeed
|
||||
# # - add foo2 to nonetwork
|
||||
# # - remove foo3 from default
|
||||
# # - remove foo4 from default
|
||||
# services:
|
||||
# - name: foo1
|
||||
# mandatory: true
|
||||
# - name: foo2
|
||||
# runlevel: nonetwork
|
||||
# disable:
|
||||
# - name: foo3
|
||||
# runlevel: default
|
||||
# - foo4
|
||||
services: []
|
||||
disable: []
|
||||
|
Reference in New Issue
Block a user