From a878c1a6109349c8f7182663fae60932a109af9c Mon Sep 17 00:00:00 2001 From: udeved Date: Mon, 28 May 2018 01:31:55 +0200 Subject: [PATCH 01/40] add openrccfg --- src/modules/openrccfg/main.py | 58 ++++++++++++++++++++++++++++ src/modules/openrccfg/module.desc | 5 +++ src/modules/openrccfg/openrccfg.conf | 8 ++++ 3 files changed, 71 insertions(+) create mode 100644 src/modules/openrccfg/main.py create mode 100644 src/modules/openrccfg/module.desc create mode 100644 src/modules/openrccfg/openrccfg.conf diff --git a/src/modules/openrccfg/main.py b/src/modules/openrccfg/main.py new file mode 100644 index 000000000..724b02c3f --- /dev/null +++ b/src/modules/openrccfg/main.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# === This file is part of Calamares - === +# +# Copyright 2016, Artoo +# Copyright 2017, Philip Müller +# Copyright 2018, Artoo +# +# Calamares is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Calamares is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty 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 Calamares. If not, see . + +import libcalamares + +from libcalamares.utils import target_env_call +from os.path import exists, join + + +class OpenrcController: + """This is the service controller + """ + + def __init__(self): + self.root = libcalamares.globalstorage.value('rootMountPoint') + self.services = libcalamares.job.configuration.get('services', []) + + def update(self, state): + """Update init scripts + """ + + for svc in self.services[state]: + if exists(self.root + "/etc/init.d/" + svc["name"]): + target_env_call( + ["rc-update", state, svc["name"], svc["runlevel"]] + ) + + def run(self): + """Run the controller + """ + + for state in self.services.keys(): + self.update(state) + +def run(): + """Setup services + """ + + return OpenrcController().run() diff --git a/src/modules/openrccfg/module.desc b/src/modules/openrccfg/module.desc new file mode 100644 index 000000000..1be7af923 --- /dev/null +++ b/src/modules/openrccfg/module.desc @@ -0,0 +1,5 @@ +--- +type: "job" +name: "openrccfg" +interface: "python" +script: "main.py" diff --git a/src/modules/openrccfg/openrccfg.conf b/src/modules/openrccfg/openrccfg.conf new file mode 100644 index 000000000..e10da15ce --- /dev/null +++ b/src/modules/openrccfg/openrccfg.conf @@ -0,0 +1,8 @@ +--- +services: + add: + - name: "NetworkManager" + runlevel: "default" +# del: +# - name: "hwclock" +# runlevel: "boot" From 88e082d53185b1b559feaca2c3062279a27111b3 Mon Sep 17 00:00:00 2001 From: udeved Date: Sun, 3 Jun 2018 22:30:08 +0200 Subject: [PATCH 02/40] openrccfg: add small documentation in conf, make service location configurable --- src/modules/openrccfg/main.py | 15 ++++++----- src/modules/openrccfg/openrccfg.conf | 37 +++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/modules/openrccfg/main.py b/src/modules/openrccfg/main.py index 724b02c3f..9dc6bf1ff 100644 --- a/src/modules/openrccfg/main.py +++ b/src/modules/openrccfg/main.py @@ -27,22 +27,25 @@ from os.path import exists, join class OpenrcController: - """This is the service controller + """This is the openrc service controller """ def __init__(self): self.root = libcalamares.globalstorage.value('rootMountPoint') self.services = libcalamares.job.configuration.get('services', []) + self.initdDir = libcalamares.job.configuration['initdDir'] + self.runlevelsDir = libcalamares.job.configuration['runlevelsDir'] def update(self, state): - """Update init scripts + """call rc-update for each service listed """ for svc in self.services[state]: - if exists(self.root + "/etc/init.d/" + svc["name"]): - target_env_call( - ["rc-update", state, svc["name"], svc["runlevel"]] - ) + if exists(self.root + self.initdDir + "/" + svc["name"]): + if exists(self.root + self.runlevelsDir + "/" + svc["runlevel"]): + target_env_call( + ["rc-update", state, svc["name"], svc["runlevel"]] + ) def run(self): """Run the controller diff --git a/src/modules/openrccfg/openrccfg.conf b/src/modules/openrccfg/openrccfg.conf index e10da15ce..efd56bc14 100644 --- a/src/modules/openrccfg/openrccfg.conf +++ b/src/modules/openrccfg/openrccfg.conf @@ -1,8 +1,39 @@ +# operccfg +# openrc services module to set service runlevels via rc-update in the chroot +# +# format of the conf +### +# services: +# add: +# - name: foo1 +# runlevel: default +# - name: foo2 +# runlevel: nonetwork +# del: +# - name: foo3 +# runlevel: default +# +# initdDir: /etc/init.d +# +# runlevelsDir: /etc/runlevels +#### +# add: list of services and their runlevels to add +# del: list of services and their runlevels to delete +# name: the service name +# runlevel: can hold any runlevel present on the target system +# initdDir: holds the openrc service directory location +# runlevelsDir: holds the runlevels directory location +# +# 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 +# --- services: add: - name: "NetworkManager" runlevel: "default" -# del: -# - name: "hwclock" -# runlevel: "boot" + +initdDir: /etc/init.d + +runlevelsDir: /etc/runlevels From a6688504e801e1eecc2a3e68bcb51e3f8ff7ad1e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 04:17:03 -0400 Subject: [PATCH 05/40] CMake: switch INSTALL_CONFIG to OFF by default - The examples files are not harmless, so distro's should take a explicit decision to install the config examples (instead of putting files in /etc/calamares). --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5eed360f8..d72463bbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ cmake_minimum_required( VERSION 3.2 ) ### OPTIONS # -option( INSTALL_CONFIG "Install configuration files" ON ) +option( INSTALL_CONFIG "Install configuration files" OFF ) option( INSTALL_POLKIT "Install Polkit configuration" ON ) option( BUILD_TESTING "Build the testing tree." ON ) option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) From 29830bc1e12c0a4481fd7b7e58701a73d03768ec Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 04:35:00 -0400 Subject: [PATCH 06/40] [services] Document the configuration file. - Change the example to be harmless (empty) - Document the structure of the entries --- src/modules/services/services.conf | 57 +++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/modules/services/services.conf b/src/modules/services/services.conf index d9c8895ea..eb971b222 100644 --- a/src/modules/services/services.conf +++ b/src/modules/services/services.conf @@ -1,20 +1,45 @@ +# Systemd services manipulation. +# +# This module can enable services and targets for systemd +# (if packaging doesn't already do that). It can calso +# disable services (but not targets). +# +# First, services are enabled; then targets; then services +# are disabled -- this order of operations is fixed. --- -#systemd services and targets are enabled in this precise order -services: - - name: "NetworkManager" #name of the service file - mandatory: false #true=> if enabling fails the installer errors out and quits - #false=>if enabling fails print warning to console and continue - - name: "cups" - mandatory: false +# There are three configuration keys for this module: +# *services*, *targets* and *disable*. 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. +# - *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 entry (service or target) are ignored. +# +# Use [] to express an empty list. -targets: - - name: "graphical" - mandatory: true +# # This example enables NetworkManager (and fails if it can't), +# # disables cups (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). +# # +# services: +# - name: "NetworkManager" +# mandatory: true +# - name: "cups" +# mandatory: false +# +# targets: +# - name: "graphical" +# mandatory: true +# +# disable: +# - name: "pacman-init" +# mandatory: false -disable: - - name: "pacman-init" - mandatory: false - -# Example to express an empty list: -# disable: [] +# By default, no changes are made. +services: [] +targets: [] +disable: [] From b2c2b916456972b5ce5e0ac140c3a568b7c48a8a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 05:18:10 -0400 Subject: [PATCH 07/40] CMake: introduce USE_ When there are multiple modules doing a thing and it really only makes sense to have one of them in a given Calamares compilation, the USE_ variables allow you to select one, while ignoring all the other implementations. If USE_ is not set, all implementations are included (as usual). --- CMakeLists.txt | 16 ++++++++++++++++ src/modules/CMakeLists.txt | 20 +++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d72463bbd..1fa59421c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,22 @@ option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." ON ) option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) +### USE_* +# +# By convention, when there are multiple modules that implement similar +# functionality, and it only makes sense to have **at most one** of them +# enabled at any time, those modules are named -. +# For example, services-systemd and services-openrc. +# +# Setting up SKIP_MODULES to ignore "the ones you don't want" can be +# annoying and error-prone (e.g. if a new module shows up). The USE_* +# modules provide a way to do automatic selection. To pick exactly +# one of the implementations from group , set USE_ to the +# name of the implementation. If USE_ is unset, or empty, then +# all the implementations are enabled (this just means they are +# **available** to `settings.conf`, not that they are used). +# +# Currently, no USE_ variables exist. ### Calamares application info # diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 514d6b4f6..bf1817b52 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -15,13 +15,31 @@ string( REPLACE " " ";" SKIP_LIST "${SKIP_MODULES}" ) file( GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*" ) list( SORT SUBDIRECTORIES ) +# Handle the USE_ variables by looking for subdirectories +# with a - kind of name. +foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) +endforeach() + foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) list( FIND SKIP_LIST ${SUBDIRECTORY} DO_SKIP ) + set( _skip_reason "user request" ) + if( SUBDIRECTORY MATCHES "^[a-zA-Z0-9_]+-" ) + string( REGEX REPLACE "^[^-]+-" "" _implementation ${SUBDIRECTORY} ) + string( REGEX REPLACE "-.*" "" _category ${SUBDIRECTORY} ) + if( USE_${_category} ) + if( NOT "${_implementation}" STREQUAL "${USE_${_category}}" ) + list( APPEND SKIP_LIST ${SUBDIRECTORY} ) + set( _skip_reason "USE_${_category}=${USE_${_category}}" ) + set( DO_SKIP 1 ) + endif() + endif() + endif() + if( NOT DO_SKIP EQUAL -1 ) message( "${ColorReset}-- Skipping module ${BoldRed}${SUBDIRECTORY}${ColorReset}." ) message( "" ) - list( APPEND LIST_SKIPPED_MODULES "${SUBDIRECTORY} (user request)" ) + list( APPEND LIST_SKIPPED_MODULES "${SUBDIRECTORY} (${_skip_reason})" ) elseif( ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}" ) AND ( DO_SKIP EQUAL -1 ) ) set( SKIPPED_MODULES ) From c086d18a26a5f2d62f9dc1fb2ef646b47585b622 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 05:33:01 -0400 Subject: [PATCH 08/40] CMake: improve error-handling for USE_* If USE_ is given a value that doesn't match **anything**, then bail out. Since USE_* is an explicit distro choice for a specific implementation, it's an error if that implementation is not there. --- src/modules/CMakeLists.txt | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index bf1817b52..0a8d1db70 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -15,20 +15,23 @@ string( REPLACE " " ";" SKIP_LIST "${SKIP_MODULES}" ) file( GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*" ) list( SORT SUBDIRECTORIES ) -# Handle the USE_ variables by looking for subdirectories -# with a - kind of name. -foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) -endforeach() +set( _use_categories "" ) +set( _found_categories "" ) foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) list( FIND SKIP_LIST ${SUBDIRECTORY} DO_SKIP ) set( _skip_reason "user request" ) + # Handle the USE_ variables by looking for subdirectories + # with a - kind of name. if( SUBDIRECTORY MATCHES "^[a-zA-Z0-9_]+-" ) string( REGEX REPLACE "^[^-]+-" "" _implementation ${SUBDIRECTORY} ) string( REGEX REPLACE "-.*" "" _category ${SUBDIRECTORY} ) if( USE_${_category} ) - if( NOT "${_implementation}" STREQUAL "${USE_${_category}}" ) + list( APPEND _use_categories ${_category} ) + if( "${_implementation}" STREQUAL "${USE_${_category}}" ) + list( APPEND _found_categories ${_category} ) + else() list( APPEND SKIP_LIST ${SUBDIRECTORY} ) set( _skip_reason "USE_${_category}=${USE_${_category}}" ) set( DO_SKIP 1 ) @@ -54,5 +57,12 @@ endforeach() # both before and after the feature summary. calamares_explain_skipped_modules( ${LIST_SKIPPED_MODULES} ) +foreach( _category ${_use_categories} ) + list( FIND _found_categories ${_category} _found ) + if ( _found EQUAL -1 ) + message( FATAL_ERROR "USE_${_category} is set to ${USE_${_category}} and no module matches." ) + endif() +endforeach() + include( CalamaresAddTranslations ) add_calamares_python_translations( ${CALAMARES_TRANSLATION_LANGUAGES} ) From 52f09f7f462c36d559b1bd536bc1f140f0620365 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 05:47:23 -0400 Subject: [PATCH 09/40] [modules] Minor documentation work on modules a-g --- src/modules/bootloader/bootloader.conf | 2 ++ src/modules/displaymanager/displaymanager.conf | 2 ++ src/modules/dummycpp/dummycpp.conf | 5 ++++- src/modules/dummypython/dummypython.conf | 5 ++++- src/modules/dummypythonqt/dummypythonqt.conf | 3 +++ src/modules/grubcfg/grubcfg.conf | 1 + 6 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/modules/bootloader/bootloader.conf b/src/modules/bootloader/bootloader.conf index ee8680f72..808a5e6d0 100644 --- a/src/modules/bootloader/bootloader.conf +++ b/src/modules/bootloader/bootloader.conf @@ -12,8 +12,10 @@ kernel: "/vmlinuz-linux" img: "/initramfs-linux.img" fallback: "/initramfs-linux-fallback.img" timeout: "10" + # Optionally set the menu entry name and kernel name to use in systemd-boot. # If not specified here, these settings will be taken from branding.desc. +# # bootloaderEntryName: "Generic GNU/Linux" # kernelLine: ", with Stable-Kernel" # fallbackKernelLine: ", with Stable-Kernel (fallback initramfs)" diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf index 1c30ed637..8f8e9c704 100644 --- a/src/modules/displaymanager/displaymanager.conf +++ b/src/modules/displaymanager/displaymanager.conf @@ -1,3 +1,5 @@ +# Configure one or more display managers (e.g. SDDM) +# with a "best effort" approach. --- #The DM module attempts to set up all the DMs found in this list, in that precise order. #It also sets up autologin, if the feature is enabled in globalstorage. diff --git a/src/modules/dummycpp/dummycpp.conf b/src/modules/dummycpp/dummycpp.conf index c90b6f3b9..1f2e1daee 100644 --- a/src/modules/dummycpp/dummycpp.conf +++ b/src/modules/dummycpp/dummycpp.conf @@ -1,3 +1,6 @@ +# This is a dummy (example) module for C++ Jobs. +# +# The code is the documentation for the configuration file. --- syntax: "YAML map of anything" example: @@ -15,4 +18,4 @@ a_list_of_maps: - "another element" - name: "another item" contents: - - "not much" \ No newline at end of file + - "not much" diff --git a/src/modules/dummypython/dummypython.conf b/src/modules/dummypython/dummypython.conf index fc985089a..c700120e7 100644 --- a/src/modules/dummypython/dummypython.conf +++ b/src/modules/dummypython/dummypython.conf @@ -1,3 +1,6 @@ +# This is a dummy (example) module for a Python Job Module. +# +# The code is the documentation for the configuration file. --- syntax: "YAML map of anything" example: @@ -15,4 +18,4 @@ a_list_of_maps: - "another element" - name: "another item" contents: - - "not much" \ No newline at end of file + - "not much" diff --git a/src/modules/dummypythonqt/dummypythonqt.conf b/src/modules/dummypythonqt/dummypythonqt.conf index f60e778e1..5bc64abfa 100644 --- a/src/modules/dummypythonqt/dummypythonqt.conf +++ b/src/modules/dummypythonqt/dummypythonqt.conf @@ -1,3 +1,6 @@ +# This is a dummy (example) module for PythonQt. +# +# The code is the documentation for the configuration file. --- syntax: "YAML map of anything" example: diff --git a/src/modules/grubcfg/grubcfg.conf b/src/modules/grubcfg/grubcfg.conf index 608c9b2b4..18951a8a6 100644 --- a/src/modules/grubcfg/grubcfg.conf +++ b/src/modules/grubcfg/grubcfg.conf @@ -2,6 +2,7 @@ # If set to true, always creates /etc/default/grub from scratch even if the file # already existed. If set to false, edits the existing file instead. overwrite: false + # Default entries to write to /etc/default/grub if it does not exist yet or if # we are overwriting it. Note that in addition, GRUB_CMDLINE_LINUX_DEFAULT and # GRUB_DISTRIBUTOR will always be written, with automatically detected values. From 63c03068c0cda4f71b8bd0bf2a8c1b870eaa3008 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 06:39:30 -0400 Subject: [PATCH 10/40] [modules] Documentation for fstab, grubcfg, mkinitcpio - These modules were entirely documented as "use the source", - The sources aren't terribly clear either. --- src/modules/fstab/fstab.conf | 15 +++++++++++++++ src/modules/grubcfg/grubcfg.conf | 15 +++++++++++++-- src/modules/initcpio/initcpio.conf | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf index c3dbfc309..11adff2ed 100644 --- a/src/modules/fstab/fstab.conf +++ b/src/modules/fstab/fstab.conf @@ -1,13 +1,28 @@ +# Creates /etc/fstab and /etc/crypttab in the target system. +# Also creates mount points for all the filesystems. +# +# When creating fstab entries for a filesystem, this module +# uses the options for the filesystem type to write to the +# options field of the file. --- +# Mount options to use for all filesystems. If a specific filesystem +# is listed here, use those options, otherwise use the *default* +# options from this mapping. mountOptions: default: defaults,noatime btrfs: defaults,noatime,space_cache,autodefrag + +# If a filesystem is on an SSD, add the following options. If a specific +# filesystem is listed here, use those options, otherwise no additional +# options are set (i.e. there is no *default* like in *mountOptions*). ssdExtraMountOptions: ext4: discard jfs: discard xfs: discard swap: discard btrfs: discard,compress=lzo + +# Additional options added to each line in /etc/crypttab crypttabOptions: luks # For Debian and Debian-based distributions, change the above line to: # crypttabOptions: luks,keyscript=/bin/cat diff --git a/src/modules/grubcfg/grubcfg.conf b/src/modules/grubcfg/grubcfg.conf index 18951a8a6..b354ec35a 100644 --- a/src/modules/grubcfg/grubcfg.conf +++ b/src/modules/grubcfg/grubcfg.conf @@ -1,11 +1,22 @@ +# Write lines to /etc/default/grub (in the target system) based +# on calculated values and the values set in the *defaults* key +# in this configuration file. +# +# Calculated values are: +# - GRUB_DISTRIBUTOR, branding module, *bootloaderEntryName* +# - GRUB_ENABLE_CRYPTODISK, based on the presence of filesystems +# that use LUKS +# - GRUB_CMDLINE_LINUX_DEFAULT, adding LUKS setup and plymouth +# support to the kernel. + --- # If set to true, always creates /etc/default/grub from scratch even if the file # already existed. If set to false, edits the existing file instead. overwrite: false # Default entries to write to /etc/default/grub if it does not exist yet or if -# we are overwriting it. Note that in addition, GRUB_CMDLINE_LINUX_DEFAULT and -# GRUB_DISTRIBUTOR will always be written, with automatically detected values. +# we are overwriting it. +# defaults: GRUB_TIMEOUT: 5 GRUB_DEFAULT: "saved" diff --git a/src/modules/initcpio/initcpio.conf b/src/modules/initcpio/initcpio.conf index 21f5704cc..466a8785d 100644 --- a/src/modules/initcpio/initcpio.conf +++ b/src/modules/initcpio/initcpio.conf @@ -1,2 +1,3 @@ +# Run mkinitcpio(8) with the given preset value --- kernel: linux312 From 1eede6f79719377bac7004bdebed5ef54abc5232 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 06:50:16 -0400 Subject: [PATCH 11/40] [modules] Configuration documentation for mount and luksopenswaphookcfg --- .../luksopenswaphookcfg/luksopenswaphookcfg.conf | 2 ++ src/modules/mount/mount.conf | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf b/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf index 886867f8d..f5610cd7c 100644 --- a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf +++ b/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf @@ -1,2 +1,4 @@ +# Writes an openswap configuration with LUKS settings to the given path --- +# Path of the configuration file to write (in the target system) configFilePath: /etc/openswap.conf diff --git a/src/modules/mount/mount.conf b/src/modules/mount/mount.conf index d8f8fb8cc..bb28eed66 100644 --- a/src/modules/mount/mount.conf +++ b/src/modules/mount/mount.conf @@ -1,4 +1,18 @@ +# Mount filesystems in the target (generally, before treating the +# target as a usable chroot / "live" system). Filesystems are +# automatically mounted from the partitioning module. Filesystems +# listed here are **extra**. The filesystems listed in *extraMounts* +# are mounted in all target systems. The filesystems listed in +# *extraMountsEfi* are mounted in the target system **only** if +# the host machine uses UEFI. --- +# Extra filesystems to mount. The key's value is a list of entries; each +# entry has four keys: +# - device The device node to mount +# - fs The filesystem type to use +# - mountPoint Where to mount the filesystem +# - options (optional) Extra options to pass to mount(8) +# extraMounts: - device: proc fs: proc From 40252f1000eb2453dc6661e4bc300bf0e462170f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 06:52:37 -0400 Subject: [PATCH 12/40] [removeuser] Minor documentation --- src/modules/removeuser/removeuser.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/removeuser/removeuser.conf b/src/modules/removeuser/removeuser.conf index a59961ec5..dab4b2526 100644 --- a/src/modules/removeuser/removeuser.conf +++ b/src/modules/removeuser/removeuser.conf @@ -1,2 +1,6 @@ +# Removes a single user (with userdel) from the system. +# This is typically used in OEM setups or if the live user +# spills into the target system. --- +# Username in the target system to be removed. username: live From 731594fb40456b1676725659e13213760bc180a2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 08:07:36 -0400 Subject: [PATCH 13/40] [libcalamaresui] Remove the requiredModules setting - The value set in module.desc was never stored for use, but isn't an attribute of the instance, either. It belongs with the descriptor, in ModuleManager. --- src/libcalamaresui/modulesystem/Module.cpp | 8 -------- src/libcalamaresui/modulesystem/Module.h | 8 -------- 2 files changed, 16 deletions(-) diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index c820b98b3..ed1cb33ea 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -224,13 +224,6 @@ Module::instanceKey() const } -QStringList -Module::requiredModules() const -{ - return m_requiredModules; -} - - QString Module::location() const { @@ -286,7 +279,6 @@ void Module::initFrom( const QVariantMap& moduleDescriptor ) { m_name = moduleDescriptor.value( "name" ).toString(); - if ( moduleDescriptor.contains( EMERGENCY ) ) m_maybe_emergency = moduleDescriptor[ EMERGENCY ].toBool(); } diff --git a/src/libcalamaresui/modulesystem/Module.h b/src/libcalamaresui/modulesystem/Module.h index 18c2e4cbe..f89c9eedb 100644 --- a/src/libcalamaresui/modulesystem/Module.h +++ b/src/libcalamaresui/modulesystem/Module.h @@ -106,13 +106,6 @@ public: */ virtual QString instanceKey() const final; - /** - * @brief requiredModules a list of names of modules required by this one. - * @return the list of names. - * The module dependencies system is currently incomplete and unused. - */ - virtual QStringList requiredModules() const; - /** * @brief location returns the full path of this module's directory. * @return the path. @@ -198,7 +191,6 @@ private: void loadConfigurationFile( const QString& configFileName ); //throws YAML::Exception QString m_name; - QStringList m_requiredModules; QString m_directory; QString m_instanceId; From 08966ff9334cc28ee01524bce5a113aff5466cf2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 08:29:33 -0400 Subject: [PATCH 14/40] [libcalamaresui] Check module dependencies - Module dependency-checking is done in two phases: first, catch any unknown modules that are listed in *requiredModules* and bail out before loading anything. Second, check that the modules required by X occur before X in the sequence. --- .../modulesystem/ModuleManager.cpp | 54 +++++++++++++++++-- .../modulesystem/ModuleManager.h | 20 ++++++- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index ed1e52f9f..24bc6bc53 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -126,7 +126,6 @@ ModuleManager::doInit() } // At this point m_availableModules is filled with whatever was found in the // search paths. - checkDependencies(); emit initDone(); } @@ -176,7 +175,13 @@ ModuleManager::loadModules() { QTimer::singleShot( 0, this, [ this ]() { - QStringList failedModules; + QStringList failedModules = checkDependencies(); + if ( !failedModules.isEmpty() ) + { + emit modulesFailed( failedModules ); + return; + } + Settings::InstanceDescriptionList customInstances = Settings::instance()->customModuleInstances(); @@ -262,6 +267,14 @@ ModuleManager::loadModules() failedModules.append( instanceKey ); continue; } + + if ( !checkDependencies( *thisModule ) ) + { + // Error message is already printed + failedModules.append( instanceKey ); + continue; + } + // If it's a ViewModule, it also appends the ViewStep to the ViewManager. thisModule->loadSelf(); m_loadedModulesByInstanceKey.insert( instanceKey, thisModule ); @@ -301,24 +314,29 @@ ModuleManager::loadModules() } -void +QStringList ModuleManager::checkDependencies() { + QStringList failed; + // This goes through the map of available modules, and deletes those whose // dependencies are not met, if any. - bool somethingWasRemovedBecauseOfUnmetDependencies = false; forever { + bool somethingWasRemovedBecauseOfUnmetDependencies = false; for ( auto it = m_availableDescriptorsByModuleName.begin(); it != m_availableDescriptorsByModuleName.end(); ++it ) { foreach ( const QString& depName, - ( *it ).value( "requiredModules" ).toStringList() ) + it->value( "requiredModules" ).toStringList() ) { if ( !m_availableDescriptorsByModuleName.contains( depName ) ) { + QString moduleName = it->value( "name" ).toString(); somethingWasRemovedBecauseOfUnmetDependencies = true; m_availableDescriptorsByModuleName.erase( it ); + failed << moduleName; + cWarning() << "Module" << moduleName << "has unmet requirement" << depName; break; } } @@ -328,7 +346,33 @@ ModuleManager::checkDependencies() if ( !somethingWasRemovedBecauseOfUnmetDependencies ) break; } + + return failed; } +bool +ModuleManager::checkDependencies( const Module& m ) +{ + bool allRequirementsFound = true; + QStringList requiredModules = m_availableDescriptorsByModuleName[ m.name() ].value( "requiredModules" ).toStringList(); + + for ( const QString& required : requiredModules ) + { + bool requirementFound = false; + for( const Module* v : m_loadedModulesByInstanceKey ) + if ( required == v->name() ) + { + requirementFound = true; + break; + } + if ( !requirementFound ) + { + cError() << "Module" << m.name() << "requires" << required << "before it in sequence."; + allRequirementsFound = false; + } + } + + return allRequirementsFound; +} } diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index eff09b321..a0edc2528 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -90,7 +90,25 @@ private slots: void doInit(); private: - void checkDependencies(); + /** + * Check in a general sense whether the dependencies between + * modules are valid. Returns a list of module names that + * do **not** have their requirements met. + * + * Returns an empty list on success. + * + * Also modifies m_availableDescriptorsByModuleName to remove + * all the entries that fail. + */ + QStringList checkDependencies(); + + /** + * Check for this specific module if its required modules have + * already been loaded (i.e. are in sequence before it). + * + * Returns true if the requirements are met. + */ + bool checkDependencies( const Module& ); QMap< QString, QVariantMap > m_availableDescriptorsByModuleName; QMap< QString, QString > m_moduleDirectoriesByModuleName; From 0db8082ae1972f0d882c071427a3bc7ab8d5600a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 08:41:16 -0400 Subject: [PATCH 15/40] [libcalamares] Convenience type --- src/libcalamares/Settings.cpp | 2 +- src/libcalamares/Settings.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 1fdfc6daa..8fd4eeac3 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -212,7 +212,7 @@ Settings::customModuleInstances() const } -QList< QPair< ModuleAction, QStringList > > +Settings::ModuleSequence Settings::modulesSequence() const { return m_modulesSequence; diff --git a/src/libcalamares/Settings.h b/src/libcalamares/Settings.h index 2330f5747..4da65f710 100644 --- a/src/libcalamares/Settings.h +++ b/src/libcalamares/Settings.h @@ -47,7 +47,8 @@ public: using InstanceDescriptionList = QList< InstanceDescription >; InstanceDescriptionList customModuleInstances() const; - QList< QPair< ModuleAction, QStringList > > modulesSequence() const; + using ModuleSequence = QList< QPair< ModuleAction, QStringList > >; + ModuleSequence modulesSequence() const; QString brandingComponentName() const; @@ -63,7 +64,7 @@ private: QStringList m_modulesSearchPaths; InstanceDescriptionList m_customModuleInstances; - QList< QPair< ModuleAction, QStringList > > m_modulesSequence; + ModuleSequence m_modulesSequence; QString m_brandingComponentName; From d66393f1aeac1efbfa8b990bca6ff8f69df48429 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 08:43:23 -0400 Subject: [PATCH 16/40] [libcalamares] Fix early failure mode - There is more to failing out of loadModules() than just emitting modulesFailed, so instead share the failure code with the code after loading modules -- but don't load any. --- src/libcalamaresui/modulesystem/ModuleManager.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 24bc6bc53..86d97d2db 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -176,16 +176,10 @@ ModuleManager::loadModules() QTimer::singleShot( 0, this, [ this ]() { QStringList failedModules = checkDependencies(); - if ( !failedModules.isEmpty() ) - { - emit modulesFailed( failedModules ); - return; - } - Settings::InstanceDescriptionList customInstances = Settings::instance()->customModuleInstances(); - const auto modulesSequence = Settings::instance()->modulesSequence(); + const auto modulesSequence = failedModules.isEmpty() ? Settings::instance()->modulesSequence() : Settings::ModuleSequence(); for ( const auto& modulePhase : modulesSequence ) { ModuleAction currentAction = modulePhase.first; @@ -336,7 +330,7 @@ ModuleManager::checkDependencies() somethingWasRemovedBecauseOfUnmetDependencies = true; m_availableDescriptorsByModuleName.erase( it ); failed << moduleName; - cWarning() << "Module" << moduleName << "has unmet requirement" << depName; + cWarning() << "Module" << moduleName << "has unknown requirement" << depName; break; } } From 08fc93f13775735968534ce2a2a25fa2aba554e3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 10:46:55 -0400 Subject: [PATCH 17/40] [services] Rename to services-systemd --- settings.conf | 2 +- src/modules/{services => services-systemd}/main.py | 0 src/modules/{services => services-systemd}/module.desc | 2 +- .../services.conf => services-systemd/services-systemd.conf} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename src/modules/{services => services-systemd}/main.py (100%) rename src/modules/{services => services-systemd}/module.desc (72%) rename src/modules/{services/services.conf => services-systemd/services-systemd.conf} (100%) diff --git a/settings.conf b/settings.conf index 546b08d39..1c95721b7 100644 --- a/settings.conf +++ b/settings.conf @@ -102,7 +102,7 @@ sequence: - displaymanager - networkcfg - hwclock - - services + - services-systemd # - dracut - initramfs # - grubcfg diff --git a/src/modules/services/main.py b/src/modules/services-systemd/main.py similarity index 100% rename from src/modules/services/main.py rename to src/modules/services-systemd/main.py diff --git a/src/modules/services/module.desc b/src/modules/services-systemd/module.desc similarity index 72% rename from src/modules/services/module.desc rename to src/modules/services-systemd/module.desc index eff1dcc63..4a72b658b 100644 --- a/src/modules/services/module.desc +++ b/src/modules/services-systemd/module.desc @@ -1,6 +1,6 @@ --- type: "job" -name: "services" +name: "services-systemd" interface: "python" requires: [] script: "main.py" diff --git a/src/modules/services/services.conf b/src/modules/services-systemd/services-systemd.conf similarity index 100% rename from src/modules/services/services.conf rename to src/modules/services-systemd/services-systemd.conf From 0e314447eca6f5503cb9db7042bb108c7af04ba9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Jun 2018 10:55:27 -0400 Subject: [PATCH 18/40] CMake: show the USE variable for services --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fa59421c..c06beba29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) # **available** to `settings.conf`, not that they are used). # # Currently, no USE_ variables exist. +set( USE_services "" CACHE STRING "Select the services module to use" ) ### Calamares application info # From 0520fc3b7e73754a330e8c3ced0227cc2a93fd51 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 05:07:18 -0400 Subject: [PATCH 19/40] [services-systemd] Refactor to repeat less code - The three steps of modifying services in the target system do basically the same thing, so factor out the loops and logging into a systemctl() function. - Log to warning() instead of just debugging, on failure. --- src/modules/services-systemd/main.py | 99 +++++++++++----------------- 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 48e61d882..a2b2dd4f4 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -23,6 +23,36 @@ import libcalamares +def systemctl(targets, command, suffix): + """ + For each entry in @p targets, run "systemctl ", + where is the entry's name plus the given @p suffix. + A dot is added between name and suffix. + + Returns a failure message, or None if this was successful. + Services that are not mandatory have their failures suppressed + silently. + """ + for svc in targets: + ec = libcalamares.utils.target_env_call( + ['systemctl', command, "{}.{}".format(svc['name'], suffix)] + ) + + if ec != 0: + if svc['mandatory']: + return ("Cannot {} systemd {} {}".format(command, suffix, svc['name']), + "systemctl {} call in chroot returned error code {}".format(command, ec) + ) + else: + libcalamares.utils.warning( + "Cannot {} systemd {} {}".format(command, suffix, svc['name']) + ) + libcalamares.utils.warning( + "systemctl {} call in chroot returned error code {}".format(command, ec) + ) + return None + + def run(): """ Setup systemd services @@ -36,66 +66,17 @@ def run(): # that support that, see: # http://0pointer.de/blog/projects/changing-roots.html - # enable services - for svc in services: - ec = libcalamares.utils.target_env_call( - ['systemctl', 'enable', '{}.service'.format(svc['name'])] - ) + r = systemctl(services, "enable", "service") + if r is not None: + return r - if ec != 0: - if svc['mandatory']: - return ("Cannot enable systemd service {}".format(svc['name']), - "systemctl enable call in chroot returned error code " - "{}".format(ec) - ) - else: - libcalamares.utils.debug( - "Cannot enable systemd service {}".format(svc['name']) - ) - libcalamares.utils.debug( - "systemctl enable call in chroot returned error code " - "{}".format(ec) - ) + r = systemctl(targets, "enable", "target") + if r is not None: + return r - # enable targets - for tgt in targets: - ec = libcalamares.utils.target_env_call( - ['systemctl', 'enable', '{}.target'.format(tgt['name'])] - ) - - if ec != 0: - if tgt['mandatory']: - return ("Cannot enable systemd target {}".format(tgt['name']), - "systemctl enable call in chroot returned error code" - "{}".format(ec) - ) - else: - libcalamares.utils.debug( - "Cannot enable systemd target {}".format(tgt['name']) - ) - libcalamares.utils.debug( - "systemctl enable call in chroot returned error code " - "{}".format(ec) - ) - - for dbl in disable: - ec = libcalamares.utils.target_env_call( - ['systemctl', 'disable', '{}.service'.format(dbl['name'])] - ) - - if ec != 0: - if dbl['mandatory']: - return ("Cannot disable systemd service" - "{}".format(dbl['name']), - "systemctl disable call in chroot returned error code" - "{}".format(ec)) - else: - libcalamares.utils.debug( - "Cannot disable systemd service {}".format(dbl['name']) - ) - libcalamares.utils.debug( - "systemctl disable call in chroot returned error code " - "{}".format(ec) - ) + r = systemctl(disable, "disable", "service") + if r is not None: + return r + # This could have just been return r return None From 5d6e07712b6831b2e759c06e3eeefdae2b2bc1bd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 05:14:18 -0400 Subject: [PATCH 20/40] [services-systemd] Refactor getting config - Don't create temporary variables - Change API slightly to accomodate more (kinds of) suffixes --- src/modules/services-systemd/main.py | 14 ++++++-------- src/modules/services-systemd/services-systemd.conf | 6 +++++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index a2b2dd4f4..31d205318 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -27,7 +27,7 @@ def systemctl(targets, command, suffix): """ For each entry in @p targets, run "systemctl ", where is the entry's name plus the given @p suffix. - A dot is added between name and suffix. + (No dot is added between name and suffix; suffix may be empty) Returns a failure message, or None if this was successful. Services that are not mandatory have their failures suppressed @@ -35,7 +35,7 @@ def systemctl(targets, command, suffix): """ for svc in targets: ec = libcalamares.utils.target_env_call( - ['systemctl', command, "{}.{}".format(svc['name'], suffix)] + ['systemctl', command, "{}{}".format(svc['name'], suffix)] ) if ec != 0: @@ -57,24 +57,22 @@ def run(): """ Setup systemd services """ - services = libcalamares.job.configuration['services'] - targets = libcalamares.job.configuration['targets'] - disable = libcalamares.job.configuration['disable'] + 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(services, "enable", "service") + r = systemctl(cfg["services"], "enable", ".service") if r is not None: return r - r = systemctl(targets, "enable", "target") + r = systemctl(cfg["targets"], "enable", ".target") if r is not None: return r - r = systemctl(disable, "disable", "service") + r = systemctl(cfg["disable"], "disable", ".service") if r is not None: return r diff --git a/src/modules/services-systemd/services-systemd.conf b/src/modules/services-systemd/services-systemd.conf index eb971b222..64b95e125 100644 --- a/src/modules/services-systemd/services-systemd.conf +++ b/src/modules/services-systemd/services-systemd.conf @@ -12,7 +12,8 @@ # *services*, *targets* and *disable*. 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. +# changed. Use quotes. Don't include ".target" or ".service" +# in the name. # - *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, @@ -25,16 +26,19 @@ # # graphical target (e.g. so that SDDM runs for login), and # # finally disables pacman-init (an ArchLinux-only service). # # +# # Enables .service # services: # - name: "NetworkManager" # mandatory: true # - name: "cups" # mandatory: false # +# # Enables .target # targets: # - name: "graphical" # mandatory: true # +# # Disables .service # disable: # - name: "pacman-init" # mandatory: false From c9c777b055f6a95871d17a1d3773a0aa39281ad4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 07:09:03 -0400 Subject: [PATCH 21/40] [services-systemd] Introduce disable-targets and mask - With refactored code, introducing new kinds of actions is very few lines of code. Allow disabling targets (services was already possible). Allow masking units, but as a special case require the complete name. FIXES #975 --- src/modules/services-systemd/main.py | 9 +++++++++ src/modules/services-systemd/services-systemd.conf | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 31d205318..dce571384 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -76,5 +76,14 @@ def run(): if r is not None: return r + r = systemctl(cfg["disable-targets"], "disable", ".target") + if r is not None: + return r + + r = systemctl(cfg["mask"], "mask", "") + if r is not None: + return r + + # This could have just been return r return None diff --git a/src/modules/services-systemd/services-systemd.conf b/src/modules/services-systemd/services-systemd.conf index 64b95e125..082d63657 100644 --- a/src/modules/services-systemd/services-systemd.conf +++ b/src/modules/services-systemd/services-systemd.conf @@ -42,8 +42,22 @@ # disable: # - name: "pacman-init" # mandatory: false +# +# # Disables .target +# disable-targets: [] +# +# # 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 # By default, no changes are made. services: [] targets: [] disable: [] +disable-targets: [] +mask: [] From 59b07cc720dd3cb077e69e591b1a467abb01c057 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 07:14:18 -0400 Subject: [PATCH 22/40] [services-systemd] Be more resilient in the config - If a key is not given, use [] instead of crashing. --- src/modules/services-systemd/main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index dce571384..5ebe9066b 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -64,23 +64,23 @@ def run(): # that support that, see: # http://0pointer.de/blog/projects/changing-roots.html - r = systemctl(cfg["services"], "enable", ".service") + r = systemctl(cfg.get("services", []), "enable", ".service") if r is not None: return r - r = systemctl(cfg["targets"], "enable", ".target") + r = systemctl(cfg.get("targets", []), "enable", ".target") if r is not None: return r - r = systemctl(cfg["disable"], "disable", ".service") + r = systemctl(cfg.get("disable", []), "disable", ".service") if r is not None: return r - r = systemctl(cfg["disable-targets"], "disable", ".target") + r = systemctl(cfg.get("disable-targets", []), "disable", ".target") if r is not None: return r - r = systemctl(cfg["mask"], "mask", "") + r = systemctl(cfg.get("mask", []), "mask", "") if r is not None: return r From e1d306dc2fae9c5a41262c4d465f33864f57bc65 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:11:51 -0400 Subject: [PATCH 23/40] [services-openrc] Adjust documentation and follow renaming --- src/modules/openrccfg/openrccfg.conf | 39 ------------------- .../{openrccfg => services-openrc}/main.py | 0 .../module.desc | 2 +- .../services-openrc/services-openrc.conf | 34 ++++++++++++++++ 4 files changed, 35 insertions(+), 40 deletions(-) delete mode 100644 src/modules/openrccfg/openrccfg.conf rename src/modules/{openrccfg => services-openrc}/main.py (100%) rename src/modules/{openrccfg => services-openrc}/module.desc (68%) create mode 100644 src/modules/services-openrc/services-openrc.conf diff --git a/src/modules/openrccfg/openrccfg.conf b/src/modules/openrccfg/openrccfg.conf deleted file mode 100644 index efd56bc14..000000000 --- a/src/modules/openrccfg/openrccfg.conf +++ /dev/null @@ -1,39 +0,0 @@ -# operccfg -# openrc services module to set service runlevels via rc-update in the chroot -# -# format of the conf -### -# services: -# add: -# - name: foo1 -# runlevel: default -# - name: foo2 -# runlevel: nonetwork -# del: -# - name: foo3 -# runlevel: default -# -# initdDir: /etc/init.d -# -# runlevelsDir: /etc/runlevels -#### -# add: list of services and their runlevels to add -# del: list of services and their runlevels to delete -# name: the service name -# runlevel: can hold any runlevel present on the target system -# initdDir: holds the openrc service directory location -# runlevelsDir: holds the runlevels directory location -# -# 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 -# ---- -services: - add: - - name: "NetworkManager" - runlevel: "default" - -initdDir: /etc/init.d - -runlevelsDir: /etc/runlevels diff --git a/src/modules/openrccfg/main.py b/src/modules/services-openrc/main.py similarity index 100% rename from src/modules/openrccfg/main.py rename to src/modules/services-openrc/main.py diff --git a/src/modules/openrccfg/module.desc b/src/modules/services-openrc/module.desc similarity index 68% rename from src/modules/openrccfg/module.desc rename to src/modules/services-openrc/module.desc index 1be7af923..4b0b51614 100644 --- a/src/modules/openrccfg/module.desc +++ b/src/modules/services-openrc/module.desc @@ -1,5 +1,5 @@ --- type: "job" -name: "openrccfg" +name: "services-openrc" interface: "python" script: "main.py" diff --git a/src/modules/services-openrc/services-openrc.conf b/src/modules/services-openrc/services-openrc.conf new file mode 100644 index 000000000..1d507e578 --- /dev/null +++ b/src/modules/services-openrc/services-openrc.conf @@ -0,0 +1,34 @@ +# 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. +# +--- +# initdDir: holds the openrc service directory location +initdDir: /etc/init.d + +# runlevelsDir: holds the runlevels directory location +runlevelsDir: /etc/runlevels + +# services: each subkey of *services* is an action to take; +# supported actions are "add" and "del". The each subkey +# has a list of entries as value, and each entry has two +# fields: +# - name: the service name +# - runlevel: can hold any runlevel present on the target system +# +# # Example services: +# services: +# add: +# - name: foo1 +# runlevel: default +# - name: foo2 +# runlevel: nonetwork +# del: +# - name: foo3 +# runlevel: default +services: [] + From b1881d1cd2c1421ef125b755eff31e263a69cb2f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:19:05 -0400 Subject: [PATCH 24/40] [services-*] Adjust Copyright notices --- src/modules/services-openrc/main.py | 3 ++- src/modules/services-systemd/main.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 9dc6bf1ff..a3b273141 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# === This file is part of Calamares - === +# === This file is part of Calamares - === # # Copyright 2016, Artoo # Copyright 2017, Philip Müller # Copyright 2018, Artoo +# Copyright 2018, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 5ebe9066b..54a731cf8 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -6,6 +6,7 @@ # Copyright 2014, Philip Müller # Copyright 2014, Teo Mrnjavac # Copyright 2017, Alf Gaida +# Copyright 2018, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From cd640bda9fb682c63bebc46363e0dce90e23b2f9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:21:31 -0400 Subject: [PATCH 25/40] [services-openrc] Restrict actions - Document the functions some more - Only "state" (i.e. action) "add" and "del" make sense, avoid calling rc-update for other keys (e.g. typo's). This matches the documentation, although there might be other actions that make sense (see also services-systemd, with its enable, disable and mask actions). --- src/modules/services-openrc/main.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index a3b273141..eb0da046e 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -28,7 +28,10 @@ from os.path import exists, join class OpenrcController: - """This is the openrc service controller + """ + This is the openrc service controller. + All of its state comes from global storage and the job + configuration at initialization time. """ def __init__(self): @@ -38,7 +41,10 @@ class OpenrcController: self.runlevelsDir = libcalamares.job.configuration['runlevelsDir'] def update(self, state): - """call rc-update for each service listed + """ + 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[state]: @@ -52,11 +58,12 @@ class OpenrcController: """Run the controller """ - for state in self.services.keys(): + for state in ("add", "del"): self.update(state) def run(): - """Setup services + """ + Setup services """ return OpenrcController().run() From 8f0db9dc743c854af96fd2cf19802483ce514de5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:31:02 -0400 Subject: [PATCH 26/40] [services-openrc] Log configuration failures - If services don't exist, or runlevels don't exist, log them instead of failing completely silently. --- src/modules/services-openrc/main.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index eb0da046e..52e4838b3 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -23,7 +23,7 @@ import libcalamares -from libcalamares.utils import target_env_call +from libcalamares.utils import target_env_call, warning from os.path import exists, join @@ -47,12 +47,17 @@ class OpenrcController: is called with @p state as the command as well. """ - for svc in self.services[state]: - if exists(self.root + self.initdDir + "/" + svc["name"]): - if exists(self.root + self.runlevelsDir + "/" + svc["runlevel"]): - target_env_call( - ["rc-update", state, svc["name"], svc["runlevel"]] - ) + for svc in self.services.get(state, []): + service_path = self.root + self.initdDir + "/" + svc["name"] + runlevel_path = self.root + self.runlevelsDir + "/" + svc["runlevel"] + if exists(service_path): + if exists(runlevel_path): + target_env_call(["rc-update", state, svc["name"], svc["runlevel"]]) + else: + warning("Target runlevel {} does not exist for {}.".format(svc["runlevel"], svc["name"])) + else: + warning("Target service {} does not exist int {}.".format(svc["name"], self.initDir)) + def run(self): """Run the controller From 5a2ae7a250b77391fcc6b656fb91b00720abe5d3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:33:02 -0400 Subject: [PATCH 27/40] [services-openrc] Simplify name extraction, default runlevel - If runlevel isn't set (at all) then use "default". For most systems that do not use multiple runlevels, this simplifies the configuration to just a list of service names to add or delete. --- src/modules/services-openrc/main.py | 13 ++++++++----- src/modules/services-openrc/services-openrc.conf | 7 +++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 52e4838b3..27ea6ebb6 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -48,15 +48,18 @@ class OpenrcController: """ for svc in self.services.get(state, []): - service_path = self.root + self.initdDir + "/" + svc["name"] - runlevel_path = self.root + self.runlevelsDir + "/" + svc["runlevel"] + name = svc["name"] + runlevel = svc.get("runlevel", "default") + + service_path = self.root + self.initdDir + "/" + name + runlevel_path = self.root + self.runlevelsDir + "/" + runlevel if exists(service_path): if exists(runlevel_path): - target_env_call(["rc-update", state, svc["name"], svc["runlevel"]]) + target_env_call(["rc-update", state, name, runlevel]) else: - warning("Target runlevel {} does not exist for {}.".format(svc["runlevel"], svc["name"])) + warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) else: - warning("Target service {} does not exist int {}.".format(svc["name"], self.initDir)) + warning("Target service {} does not exist int {}.".format(name, self.initDir)) def run(self): diff --git a/src/modules/services-openrc/services-openrc.conf b/src/modules/services-openrc/services-openrc.conf index 1d507e578..61440f692 100644 --- a/src/modules/services-openrc/services-openrc.conf +++ b/src/modules/services-openrc/services-openrc.conf @@ -18,13 +18,16 @@ runlevelsDir: /etc/runlevels # has a list of entries as value, and each entry has two # fields: # - name: the service name -# - runlevel: can hold any runlevel present on the target system +# - runlevel: can hold any runlevel present on the target system; +# if no runlevel is provided, "default" is assumed. # # # Example services: +# # - add foo1 to default +# # - add foo2 to nonetwork +# # - remove foo3 from default # services: # add: # - name: foo1 -# runlevel: default # - name: foo2 # runlevel: nonetwork # del: From dbcc419218b2409f925d059b030d79d4eca1bea3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:39:30 -0400 Subject: [PATCH 28/40] [services-openrc] Log failures - If the rc-update command fails for some reason, log that failure instead of skipping it completely silently. - Fix syntax error as well --- src/modules/services-openrc/main.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 27ea6ebb6..cfa7fd457 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -53,13 +53,16 @@ class OpenrcController: service_path = self.root + self.initdDir + "/" + name runlevel_path = self.root + self.runlevelsDir + "/" + runlevel + if exists(service_path): if exists(runlevel_path): - target_env_call(["rc-update", state, name, runlevel]) + ec = target_env_call(["rc-update", state, name, runlevel]) + if ec != 0: + warning("Could not {} service {} in {}, error {!s}".format(state, name, runlevel, ec)) else: warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) else: - warning("Target service {} does not exist int {}.".format(name, self.initDir)) + warning("Target service {} does not exist in {}.".format(name, self.initdDir)) def run(self): From b02ee3cd8d033660bfdbaf1d21ad407115e67be3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 09:46:43 -0400 Subject: [PATCH 29/40] [services-openrc] Follow services-systemd configuration example - Based on comments from #974, follow the configuration scheme from services-systemd, so with separate lists "services" and "disable". This ties it **slightly** less closely to the commands passed to rc-config. --- src/modules/services-openrc/main.py | 7 +++++- .../services-openrc/services-openrc.conf | 24 +++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index cfa7fd457..63d17bcc0 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -36,7 +36,12 @@ class OpenrcController: def __init__(self): self.root = libcalamares.globalstorage.value('rootMountPoint') - self.services = libcalamares.job.configuration.get('services', []) + + # 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', []) + self.initdDir = libcalamares.job.configuration['initdDir'] self.runlevelsDir = libcalamares.job.configuration['runlevelsDir'] diff --git a/src/modules/services-openrc/services-openrc.conf b/src/modules/services-openrc/services-openrc.conf index 61440f692..c89c82a32 100644 --- a/src/modules/services-openrc/services-openrc.conf +++ b/src/modules/services-openrc/services-openrc.conf @@ -13,25 +13,25 @@ initdDir: /etc/init.d # runlevelsDir: holds the runlevels directory location runlevelsDir: /etc/runlevels -# services: each subkey of *services* is an action to take; -# supported actions are "add" and "del". The each subkey -# has a list of entries as value, and each entry has two -# fields: +# services: a list of entries to **enable** +# disable: a list of entries to **disable** +# +# Each entry has two fields: # - name: the service name # - runlevel: can hold any runlevel present on the target system; # if no runlevel is provided, "default" is assumed. # -# # Example services: +# # Example services and disable settings: # # - add foo1 to default # # - add foo2 to nonetwork # # - remove foo3 from default # services: -# add: -# - name: foo1 -# - name: foo2 -# runlevel: nonetwork -# del: -# - name: foo3 -# runlevel: default +# - name: foo1 +# - name: foo2 +# runlevel: nonetwork +# disable: +# - name: foo3 +# runlevel: default services: [] +disable: [] From 72c0d1a1012266168cd85923f426f02678d0ccc0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 10:28:32 -0400 Subject: [PATCH 30/40] [services-openrc] Make list of services more flexible - Allow just a name entry, instead of requiring an object entry; this makes "foo" equal to { name: "foo", runlevel: "default" } and simplifies more for the straightfoward case of #974. --- src/modules/services-openrc/main.py | 8 ++++++-- src/modules/services-openrc/services-openrc.conf | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 63d17bcc0..6f1d7352b 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -53,8 +53,12 @@ class OpenrcController: """ for svc in self.services.get(state, []): - name = svc["name"] - runlevel = svc.get("runlevel", "default") + if isinstance(svc, str): + name = svc + runlevel = "default" + else: + name = svc["name"] + runlevel = svc.get("runlevel", "default") service_path = self.root + self.initdDir + "/" + name runlevel_path = self.root + self.runlevelsDir + "/" + runlevel diff --git a/src/modules/services-openrc/services-openrc.conf b/src/modules/services-openrc/services-openrc.conf index c89c82a32..168fa190a 100644 --- a/src/modules/services-openrc/services-openrc.conf +++ b/src/modules/services-openrc/services-openrc.conf @@ -20,11 +20,14 @@ runlevelsDir: /etc/runlevels # - name: the service name # - runlevel: can hold any runlevel present on the target system; # if no runlevel is provided, "default" is assumed. +# an entry may also be a single string, which is interpreted +# as the name field (runlevel "default" is assumed then). # # # Example services and disable settings: # # - add foo1 to default # # - add foo2 to nonetwork # # - remove foo3 from default +# # - remove foo4 from default # services: # - name: foo1 # - name: foo2 @@ -32,6 +35,7 @@ runlevelsDir: /etc/runlevels # disable: # - name: foo3 # runlevel: default +# - foo4 services: [] disable: [] From 73ecd7320c1b44c4406268e2d2a7866c2e69379b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 11:11:21 -0400 Subject: [PATCH 31/40] [services-openrc] Introduce *mandatory* subkey - Follow services-systemd and have a *mandatory* subkey that selects for install-failure instead of just a warning. FIXES #992 --- src/modules/services-openrc/main.py | 25 ++++++++++++++++--- .../services-openrc/services-openrc.conf | 15 +++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 6f1d7352b..c3e14b481 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -56,9 +56,11 @@ class OpenrcController: 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.initdDir + "/" + name runlevel_path = self.root + self.runlevelsDir + "/" + runlevel @@ -67,11 +69,24 @@ class OpenrcController: if exists(runlevel_path): ec = target_env_call(["rc-update", state, name, runlevel]) if ec != 0: - warning("Could not {} service {} in {}, error {!s}".format(state, name, runlevel, ec)) + if mandatory: + return ("Cannot {} service {} to {}".format(state, name, runlevel), + "rc-update {} call in chroot returned error code {}".format(state, ec) + ) + else: + warning("Could not {} service {} in {}, error {!s}".format(state, name, runlevel, ec)) else: - warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) + if mandatory: + return ("Target runlevel {} does not exist for {}.".format(runlevel, name), + "No {} found.".format(runlevel_path)) + else: + warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) else: - warning("Target service {} does not exist in {}.".format(name, self.initdDir)) + if mandatory: + return ("Target service {} does not exist.".format(name), + "No {} found.".format(service_path)) + else: + warning("Target service {} does not exist in {}.".format(name, self.initdDir)) def run(self): @@ -79,7 +94,9 @@ class OpenrcController: """ for state in ("add", "del"): - self.update(state) + r = self.update(state) + if r is not None: + return r def run(): """ diff --git a/src/modules/services-openrc/services-openrc.conf b/src/modules/services-openrc/services-openrc.conf index 168fa190a..b8255b21a 100644 --- a/src/modules/services-openrc/services-openrc.conf +++ b/src/modules/services-openrc/services-openrc.conf @@ -16,20 +16,25 @@ runlevelsDir: /etc/runlevels # services: a list of entries to **enable** # disable: a list of entries to **disable** # -# Each entry has two fields: +# Each entry has three fields: # - name: the service name -# - runlevel: can hold any runlevel present on the target system; -# if no runlevel is provided, "default" is assumed. +# - (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). +# as the name field (runlevel "default" is assumed then, and not-mandatory). # # # Example services and disable settings: -# # - add foo1 to default +# # - 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: From 1957478618257944e1a67244b1448c562c3127ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 11:25:11 -0400 Subject: [PATCH 32/40] [services-systemd] Follow the flexible example of openrc - Make *mandatory* optional (and default to false); this allows shorter lists of entries - Allow degenerate entries which are just a name (which have *mandatory* set to false as well). SEE #992 --- src/modules/services-systemd/main.py | 15 +++++++++++---- .../services-systemd/services-systemd.conf | 11 +++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 54a731cf8..09263b9f0 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -35,18 +35,25 @@ def systemctl(targets, command, suffix): silently. """ for svc in targets: + if isinstance(svc, str): + name = svc + mandatory = False + else: + name = svc["name"] + mandatory = svc.get("mandatory", False) + ec = libcalamares.utils.target_env_call( - ['systemctl', command, "{}{}".format(svc['name'], suffix)] + ['systemctl', command, "{}{}".format(name, suffix)] ) if ec != 0: - if svc['mandatory']: - return ("Cannot {} systemd {} {}".format(command, suffix, svc['name']), + if mandatory: + return ("Cannot {} systemd {} {}".format(command, suffix, name), "systemctl {} call in chroot returned error code {}".format(command, ec) ) else: libcalamares.utils.warning( - "Cannot {} systemd {} {}".format(command, suffix, svc['name']) + "Cannot {} systemd {} {}".format(command, suffix, name) ) libcalamares.utils.warning( "systemctl {} call in chroot returned error code {}".format(command, ec) diff --git a/src/modules/services-systemd/services-systemd.conf b/src/modules/services-systemd/services-systemd.conf index 082d63657..6ff1409bf 100644 --- a/src/modules/services-systemd/services-systemd.conf +++ b/src/modules/services-systemd/services-systemd.conf @@ -17,7 +17,12 @@ # - *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 entry (service or target) are ignored. +# errors for that entry (service or target) 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. @@ -44,7 +49,9 @@ # mandatory: false # # # Disables .target -# disable-targets: [] +# # .. 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 From 37552c184b9509e12393532ad6cc1c7823c32255 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 12:50:20 -0400 Subject: [PATCH 33/40] ci: add a release script This is the start of a release script. The idea is to automate a whole bunch of the steps documented in ci/RELEASE.md, so that a release becomes more straightforward. Assumptions abound: basically this is going to work on my workstation, and not on any other. --- ci/RELEASE.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 ci/RELEASE.sh diff --git a/ci/RELEASE.sh b/ci/RELEASE.sh new file mode 100644 index 000000000..51ca42d4f --- /dev/null +++ b/ci/RELEASE.sh @@ -0,0 +1,23 @@ +#! /bin/sh +# +# Release script for Calamares +# +# This attempts to perform the different steps of the RELEASE.md +# document automatically. It's not tested on other machines or +# setups other than [ade]'s development VM. +# +# Assumes that the version in CMakeLists.txt has been bumped, +# and that a release of that version is desired. + +test -d .git || { echo "Not at top-level." ; exit 1 ; } +test -d src/modules || { echo "No src/modules." ; exit 1 ; } + +which cmake > /dev/null 2>&1 || { echo "No cmake(1) available." ; exit 1 ; } + +rm -rf build +mkdir build || { echo "Could not create build directory." ; exit 1 ; } +( cd build && cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } +( cd build && make test ) || { echo "Tests failed." ; exit 1 ; } + + + From cfe92252d289e13eb18b30c83fdb24f337d04f3a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 12:53:45 -0400 Subject: [PATCH 34/40] ci: if clang is available, do that build too --- ci/RELEASE.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ci/RELEASE.sh b/ci/RELEASE.sh index 51ca42d4f..528735ed9 100644 --- a/ci/RELEASE.sh +++ b/ci/RELEASE.sh @@ -19,5 +19,11 @@ mkdir build || { echo "Could not create build directory." ; exit 1 ; } ( cd build && cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } ( cd build && make test ) || { echo "Tests failed." ; exit 1 ; } - +if which clang++ > /dev/null 2>&1 ; then + # Do build again with clang + rm -rf build + mkdir build || { echo "Could not create build directory." ; exit 1 ; } + ( cd build && CC=clang CXX=clang++ cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } + ( cd build && make test ) || { echo "Tests failed." ; exit 1 ; } +fi From 9f1cfba4efbb91ddd52f3246b5614fb318a80495 Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Wed, 27 Jun 2018 12:55:48 -0400 Subject: [PATCH 35/40] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_pl.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lang/calamares_pl.ts b/lang/calamares_pl.ts index 48edd7065..706a44cf5 100644 --- a/lang/calamares_pl.ts +++ b/lang/calamares_pl.ts @@ -50,7 +50,7 @@ Blank Page - + Pusta strona @@ -192,17 +192,17 @@ Calamares Initialization Failed - + Błąd inicjacji programu Calamares %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. - + %1 nie może zostać zainstalowany. Calamares nie mógł wczytać wszystkich skonfigurowanych modułów. Jest to problem ze sposobem, w jaki Calamares jest używany przez dystrybucję. <br/>The following modules could not be loaded: - + <br/>Następujące moduły nie mogły zostać wczytane: @@ -1663,7 +1663,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone. Cre&ate - + Ut_wórz From 2f6e80dc428431247a19c16ae0f219044c10b0e2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Jun 2018 13:20:52 -0400 Subject: [PATCH 36/40] CMake: always copy the config files to the build directory. Switching to INSTALL_CONFIG=OFF breaks tests by not having them in the build directory. Some logic was coupling not-installing to not-using-in-build-dir too closely. --- .../CalamaresAddModuleSubdirectory.cmake | 13 +++++---- CMakeModules/CalamaresAddPlugin.cmake | 28 ++++++++++--------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/CMakeModules/CalamaresAddModuleSubdirectory.cmake b/CMakeModules/CalamaresAddModuleSubdirectory.cmake index af26f5a74..0b417bdf3 100644 --- a/CMakeModules/CalamaresAddModuleSubdirectory.cmake +++ b/CMakeModules/CalamaresAddModuleSubdirectory.cmake @@ -85,9 +85,11 @@ function( calamares_add_module_subdirectory ) configure_file( ${SUBDIRECTORY}/${MODULE_FILE} ${SUBDIRECTORY}/${MODULE_FILE} COPYONLY ) get_filename_component( FLEXT ${MODULE_FILE} EXT ) - if( "${FLEXT}" STREQUAL ".conf" AND INSTALL_CONFIG) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE} - DESTINATION ${MODULE_DATA_DESTINATION} ) + if( "${FLEXT}" STREQUAL ".conf" ) + if( INSTALL_CONFIG ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE} + DESTINATION ${MODULE_DATA_DESTINATION} ) + endif() list( APPEND MODULE_CONFIG_FILES ${MODULE_FILE} ) else() install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${MODULE_FILE} @@ -102,10 +104,11 @@ function( calamares_add_module_subdirectory ) message( " ${Green}MODULE_DESTINATION:${ColorReset} ${MODULE_DESTINATION}" ) if( MODULE_CONFIG_FILES ) if ( INSTALL_CONFIG ) - message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => ${MODULE_DATA_DESTINATION}" ) + set( _destination "${MODULE_DATA_DESTINATION}" ) else() - message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => [Skipping installation]" ) + set( _destination "[Build directory only]" ) endif() + message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${MODULE_CONFIG_FILES} => ${_destination}" ) endif() message( "" ) endif() diff --git a/CMakeModules/CalamaresAddPlugin.cmake b/CMakeModules/CalamaresAddPlugin.cmake index d2f878381..1bf20e4ca 100644 --- a/CMakeModules/CalamaresAddPlugin.cmake +++ b/CMakeModules/CalamaresAddPlugin.cmake @@ -66,17 +66,18 @@ function( calamares_add_plugin ) message( " ${Green}TYPE:${ColorReset} ${PLUGIN_TYPE}" ) message( " ${Green}LINK_LIBRARIES:${ColorReset} ${PLUGIN_LINK_LIBRARIES}" ) message( " ${Green}LINK_PRIVATE_LIBRARIES:${ColorReset} ${PLUGIN_LINK_PRIVATE_LIBRARIES}" ) -# message( " ${Green}SOURCES:${ColorReset} ${PLUGIN_SOURCES}" ) -# message( " ${Green}UI:${ColorReset} ${PLUGIN_UI}" ) -# message( " ${Green}EXPORT_MACRO:${ColorReset} ${PLUGIN_EXPORT_MACRO}" ) -# message( " ${Green}NO_INSTALL:${ColorReset} ${PLUGIN_NO_INSTALL}" ) message( " ${Green}PLUGIN_DESTINATION:${ColorReset} ${PLUGIN_DESTINATION}" ) if( PLUGIN_CONFIG_FILES ) + set( _destination "(unknown)" ) if ( INSTALL_CONFIG AND NOT PLUGIN_NO_INSTALL ) - message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${PLUGIN_CONFIG_FILES} => ${PLUGIN_DATA_DESTINATION}" ) + set( _destination "${PLUGIN_DATA_DESTINATION}" ) + elseif( NOT PLUGIN_NO_INSTALL ) + # Not INSTALL_CONFIG + set( _destination "[Build directory only]" ) else() - message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${PLUGIN_CONFIG_FILES} => [Skipping installation]" ) + set( _destination "[Skipping installation]" ) endif() + message( " ${Green}CONFIGURATION_FILES:${ColorReset} ${PLUGIN_CONFIG_FILES} => ${_destination}" ) endif() if( PLUGIN_RESOURCES ) message( " ${Green}RESOURCES:${ColorReset} ${PLUGIN_RESOURCES}" ) @@ -147,12 +148,13 @@ function( calamares_add_plugin ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_DESC_FILE} DESTINATION ${PLUGIN_DESTINATION} ) - if ( INSTALL_CONFIG ) - foreach( PLUGIN_CONFIG_FILE ${PLUGIN_CONFIG_FILES} ) - configure_file( ${PLUGIN_CONFIG_FILE} ${PLUGIN_CONFIG_FILE} COPYONLY ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} - DESTINATION ${PLUGIN_DATA_DESTINATION} ) - endforeach() - endif() + foreach( PLUGIN_CONFIG_FILE ${PLUGIN_CONFIG_FILES} ) + configure_file( ${PLUGIN_CONFIG_FILE} ${PLUGIN_CONFIG_FILE} COPYONLY ) + if ( INSTALL_CONFIG ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} + DESTINATION ${PLUGIN_DATA_DESTINATION} ) + endif() + endforeach() endif() endfunction() From dfb42f2b49a347c4c6020a299f5b3cab96628914 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 28 Jun 2018 05:19:32 -0400 Subject: [PATCH 37/40] CMake: add target show-version to get version information --- CMakeLists.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c06beba29..a46b0d37d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,9 @@ # Example usage: # # cmake . -DSKIP_MODULES="partition luksbootkeycfg" +# +# One special target is "show-version", which can be built +# to obtain the version number from here. project( calamares C CXX ) @@ -74,7 +77,6 @@ set( CALAMARES_VERSION_MINOR 2 ) set( CALAMARES_VERSION_PATCH 1 ) set( CALAMARES_VERSION_RC 0 ) - ### Transifex (languages) info # # complete = 100% translated, @@ -394,6 +396,15 @@ if( NOT BUILD_RELEASE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/" ) endif() endif() +# Special target for not-RC (e.g. might-be-release) builds. +# This is used by the release script to get the version. +if ( CALAMARES_VERSION_RC EQUAL 0 ) + add_custom_target(show-version + ${CMAKE_COMMAND} -E echo CALAMARES_VERSION=${CALAMARES_VERSION_SHORT} + USES_TERMINAL + ) +endif() + # enforce using constBegin, constEnd for const-iterators add_definitions( "-DQT_STRICT_ITERATORS" ) From 59dd181cfcf248b513e8ecaa01d9b863ab527b53 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 28 Jun 2018 05:48:04 -0400 Subject: [PATCH 38/40] ci: complete release script - Create tag, tarball, and test tarball - Print instructions for completing the release --- ci/RELEASE.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/ci/RELEASE.sh b/ci/RELEASE.sh index 528735ed9..d3c960fd9 100644 --- a/ci/RELEASE.sh +++ b/ci/RELEASE.sh @@ -5,25 +5,89 @@ # This attempts to perform the different steps of the RELEASE.md # document automatically. It's not tested on other machines or # setups other than [ade]'s development VM. -# +# # Assumes that the version in CMakeLists.txt has been bumped, # and that a release of that version is desired. +# +# None of the "update stuff" is done by this script; in preparation +# for the release, you should have already done: +# - updating the version +# - pulling translations +# - updating the language list +# - switching to the right branch test -d .git || { echo "Not at top-level." ; exit 1 ; } test -d src/modules || { echo "No src/modules." ; exit 1 ; } which cmake > /dev/null 2>&1 || { echo "No cmake(1) available." ; exit 1 ; } -rm -rf build -mkdir build || { echo "Could not create build directory." ; exit 1 ; } -( cd build && cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } -( cd build && make test ) || { echo "Tests failed." ; exit 1 ; } +### Build with default compiler +# +# +BUILDDIR=$(mktemp -d --suffix=-build --tmpdir=.) +rm -rf "$BUILDDIR" +mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; } +( cd "$BUILDDIR" && cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } +( cd "$BUILDDIR" && make test ) || { echo "Tests failed." ; exit 1 ; } +### Build with clang +# +# if which clang++ > /dev/null 2>&1 ; then - # Do build again with clang - rm -rf build - mkdir build || { echo "Could not create build directory." ; exit 1 ; } - ( cd build && CC=clang CXX=clang++ cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } - ( cd build && make test ) || { echo "Tests failed." ; exit 1 ; } + # Do build again with clang + rm -rf "$BUILDDIR" + mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; } + ( cd "$BUILDDIR" && CC=clang CXX=clang++ cmake .. && make -j4 ) || { echo "Could not perform test-build." ; exit 1 ; } + ( cd "$BUILDDIR" && make test ) || { echo "Tests failed." ; exit 1 ; } fi +### Get version number for this release +# +# +V=$( cd "$BUILDDIR" && make show-version | grep ^CALAMARES_VERSION | sed s/^[A-Z_]*=// ) +test -n "$V" || { echo "Could not obtain version." ; exit 1 ; } + +### Create signed tag +# +# This is the signing key ID associated with the GitHub account adriaandegroot, +# which is used to create all "verified" tags in the Calamares repo. +KEY_ID="128F00873E05AF1D" +git tag -u "$KEY_ID" "v$V" || { echo "Could not sign tag v$V." ; exit 1 ; } + +### Create the tarball +# +# +TAR_V="calamares-$V" +TAR_FILE="$TAR_V.tar.gz" +git archive -o "$TAR_FILE" --prefix "$TAR_V/" "v$V" || { echo "Could not create tarball." ; exit 1 ; } +test -f "$TAR_FILE" || { echo "Tarball was not created." ; exit 1 ; } +SHA256=$(sha256sum "$TAR_FILE" | cut -d" " -f1) + +### Build the tarball +# +# +D=$(date +%Y%m%d-%H%M%S) +TMPDIR=$(mktemp -d --suffix="-calamares-$D") +test -d "$TMPDIR" || { echo "Could not create tarball-build directory." ; exit 1 ; } +tar xzf "$TAR_FILE" -C "$TMPDIR" || { echo "Could not unpack tarball." ; exit 1 ; } +test -d "$TMPDIR/$TAR_V" || { echo "Tarball did not contain source directory." ; exit 1 ; } +( cd "$TMPDIR/$TAR_V" && cmake . && make -j4 && make test ) || { echo "Tarball build failed." ; exit 1 ; } + +### Cleanup +# +rm -rf "$BUILDDIR" # From test-builds +rm -rf "$TMPDIR" # From tarball + +### Print subsequent instructions +# +# +cat < Date: Thu, 28 Jun 2018 05:51:12 -0400 Subject: [PATCH 39/40] CMake: bump version - Set RC because this isn't near to a release yet --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a46b0d37d..183bc93f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,8 +74,8 @@ set( CALAMARES_DESCRIPTION_SUMMARY set( CALAMARES_VERSION_MAJOR 3 ) set( CALAMARES_VERSION_MINOR 2 ) -set( CALAMARES_VERSION_PATCH 1 ) -set( CALAMARES_VERSION_RC 0 ) +set( CALAMARES_VERSION_PATCH 2 ) +set( CALAMARES_VERSION_RC 1 ) ### Transifex (languages) info # From 6f39db4752c045bb9c929cbad738bde7209a22ab Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 28 Jun 2018 06:02:18 -0400 Subject: [PATCH 40/40] ci: name tags consistently --- ci/RELEASE.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/RELEASE.sh b/ci/RELEASE.sh index d3c960fd9..142d6b0c0 100644 --- a/ci/RELEASE.sh +++ b/ci/RELEASE.sh @@ -52,7 +52,7 @@ test -n "$V" || { echo "Could not obtain version." ; exit 1 ; } # This is the signing key ID associated with the GitHub account adriaandegroot, # which is used to create all "verified" tags in the Calamares repo. KEY_ID="128F00873E05AF1D" -git tag -u "$KEY_ID" "v$V" || { echo "Could not sign tag v$V." ; exit 1 ; } +git tag -u "$KEY_ID" -m "Release v$V" "v$V" || { echo "Could not sign tag v$V." ; exit 1 ; } ### Create the tarball #