Commit 50dd0523 authored by Nigel Kukard's avatar Nigel Kukard
Browse files

Added kernel selection support

parent 33ad28ef
......@@ -106,6 +106,9 @@ class Ili:
if not self.state.networknaming_strategy:
self._get_networknaming_strategy()
if not self.state.kernel:
self._get_kernels()
# Process network interface mapping before we get network config so the devices have the right names
self._plugins.process_network_interface_mapping(self.state)
......@@ -235,6 +238,10 @@ class Ili:
if self._preseed.has_option('system', 'install_microcode'):
self._status_callback('preseed system -> install_microcode')
self.state.hostname = self._preseed.getboolean('system', 'install_microcode')
# Process kernel
if self._preseed.has_option('system', 'kernel'):
self._status_callback('preseed system -> kernel')
self.state.kernel = self._preseed.get('system', 'kernel')
# Process repository section
if self._preseed.has_section('repository'):
......@@ -413,6 +420,37 @@ class Ili:
# Set the networknaming strategy
self.state.networknaming_strategy = chosen_strategy
def _get_kernels(self):
"""Get kernel to use from user."""
# Get available kernels
self._plugins.get_kernels(self.state)
chosen_kernel = ''
# Loop while no network naming strategy was selected
while not chosen_kernel:
# Display a radiolist with the kernels
code, chosen_kernel = self._dialog.radiolist(
'Select kernel to use...',
height=20, width=40, list_height=10,
title='Kernel',
choices=[
(x['kernel'], x['description'], False) for x in self.state.supported_kernels
],
)
# If the user selected cancel, we need to abort
if code == self._dialog.DIALOG_CANCEL:
exit(0)
# If no kernel was selected, we need to display an error, and do it again
if not chosen_kernel:
self._error('ERROR', 'No network naming strategy was selected!')
# Set the kernel to use
self.state.kernel = chosen_kernel
def _get_network_config(self, interface: str):
"""Get network device config from user."""
......
......@@ -38,6 +38,7 @@ class IliState:
_diskusage_strategy: Optional[str]
_disklayout_strategy: Optional[str]
_networknaming_strategy: Optional[str]
_kernel: Optional[str]
# root size in Gbytes
_root_size: int
# Hostname
......@@ -72,6 +73,7 @@ class IliState:
_supported_diskusage_strategies: List[Dict[str, str]]
_supported_disklayout_strategies: List[Dict[str, str]]
_supported_networknaming_strategies: List[Dict[str, str]]
_supported_kernels: List[Dict[str, str]]
# Block devices we'll be creating fileystems on, indexed by 'efi', 'boot', 'root'
_blockdevices: Dict[str, str]
......@@ -102,6 +104,9 @@ class IliState:
# Packages to install along with the system base
_base_packages: List[str]
# Preset to use for mkinitcpio
_mkinitcpio_preset: Optional[str]
# This property indicates that the base operating system files were installed
_base_installed: bool
......@@ -116,6 +121,7 @@ class IliState:
self._diskusage_strategy = None
self._disklayout_strategy = None
self._networknaming_strategy = None
self._kernel = None
self._root_size = 10
self._hostname = None
self._locale = 'en_US.UTF-8'
......@@ -135,6 +141,7 @@ class IliState:
self._supported_diskusage_strategies = []
self._supported_disklayout_strategies = []
self._supported_networknaming_strategies = []
self._supported_kernels = []
self._blockdevices = {}
......@@ -153,6 +160,8 @@ class IliState:
self._base_packages = []
self._mkinitcpio_preset = None
self._base_installed = False
# Check if we have an output_callback, if not set to the dummy one we have
......@@ -238,6 +247,37 @@ class IliState:
"""Set the networknaming_strategy property."""
self._networknaming_strategy = value
# Kernels
def add_kernel(self, kernel: str, description: str):
"""Add a kernel to the list of kernels supported."""
self._supported_kernels.append({'kernel': kernel, 'description': description})
@property
def supported_kernels(self):
"""Return the supported kernels property."""
return self._supported_kernels
@property
def kernel(self):
"""Return the kernel property."""
return self._kernel
@kernel.setter
def kernel(self, value: str):
"""Set the kernel property."""
self._kernel = value
@property
def mkinitcpio_preset(self):
"""Return the mkinitcpio_preset property."""
return self._kernel
@mkinitcpio_preset.setter
def mkinitcpio_preset(self, value: str):
"""Set the mkinitcpio_preset property."""
self._kernel = value
# Root size
@property
def root_size(self):
......
......@@ -44,6 +44,10 @@ class Plugin:
"""Populate state with a list of network naming strategies we can provide based on the disk usage."""
raise NotImplementedError
def get_kernels(self, ili_state: IliState):
"""Populate state with a list of kernels we can provide."""
raise NotImplementedError
def commit_diskusage_strategy(self, ili_state: IliState):
"""Commit the disk usage strategy."""
raise NotImplementedError
......@@ -117,6 +121,11 @@ class PluginCollection:
self._call_plugins(ili_state, 'get_networknaming_strategies')
def get_kernels(self, ili_state: IliState):
"""Run kernel plugins so they can add their kernels to the install state."""
self._call_plugins(ili_state, 'get_kernels')
def process_network_interface_mapping(self, ili_state: IliState):
"""Process network interface mapping."""
......
......@@ -51,5 +51,8 @@ class ConfigSystemMkinitcpio(Plugin):
sysmkinitcpio.configure(ili_state.target_root, **kwargs)
if ili_state.kernel_preset is None:
raise RuntimeError('The kernel_preset should of been set')
ili_state.output_callback('Creating mkinitcpio')
sysmkinitcpio.create(ili_state.target_root, ili_state.output_callback)
sysmkinitcpio.create(ili_state.target_root, ili_state.kernel_preset, ili_state.output_callback)
......@@ -19,6 +19,7 @@ from typing import Callable, Dict, List, Optional
from idmslinux_installer.ilistate import IliState
from idmslinux_installer.plugin import Plugin
from idmslinux_installer.util.pacman import Pacman
from idmslinux_installer.util.pacstrap import Pacstrap
......@@ -33,13 +34,48 @@ class InstallBase(Plugin):
self.description = "Install base operating system files"
Plugin.__init__(self)
def get_kernels(self, ili_state: IliState):
"""Determine kernels we support."""
# Add the kernels we support
ili_state.add_kernel('LTS', 'Long term support')
ili_state.add_kernel('STABLE', 'Latest stable')
ili_state.add_kernel('HARDENED', 'Security focused stable')
def install_base(self, ili_state: IliState):
"""Install base operating system files."""
ili_state.output_callback('Installing base packages')
# Grab base package list from pacman
pacman = Pacman()
package_list = pacman.get_group_packages('base')
# We choose the kernel below...
package_list.remove('linux')
# Remove vi and replace with vim
package_list.remove('vi')
package_list.append('vim')
# Remove mdadm, we add it ourselves if we need it
package_list.remove('mdadm')
# Remove lvm2, we add it ourselves if we need it
package_list.remove('lvm2')
# Check which kernel we're going to use
if ili_state.kernel == 'LTS':
ili_state.add_base_package('linux-lts')
ili_state.kernel_preset = 'linux-lts'
elif ili_state.kernel == 'STABLE':
ili_state.add_base_package('linux')
ili_state.kernel_preset = 'linux'
elif ili_state.kernel == 'HARDENED':
ili_state.add_base_package('linux-hardened')
ili_state.kernel_preset = 'linux-hardened'
else:
raise RuntimeError(f'Unknown kernel "{ili_state.kernel}"')
# Suck in the current package list from the install state
package_list = ['base']
package_list.extend(ili_state.base_packages)
# Run pacstrap to bootstrap the base operating system files
......
......@@ -71,7 +71,7 @@ class SysMkinitcpio:
# Move new file ontop of old one
os.replace(sys_mkinitcpio_conf_new, sys_mkinitcpio_conf)
def create(self, system_path: str, output_callback: OutputCallback = None):
def create(self, system_path: str, preset: str, output_callback: OutputCallback = None):
"""Create mkinitcpio on target system."""
# If we didn't get an output_callback, set it to our own class method
......@@ -79,8 +79,7 @@ class SysMkinitcpio:
output_callback = self._default_output_callback
# Run mkinitcpio
proc = AsyncSubprocess(['arch-chroot', system_path, 'mkinitcpio', '-p', 'linux'],
output_callback=output_callback)
proc = AsyncSubprocess(['arch-chroot', system_path, 'mkinitcpio', '-p', preset], output_callback=output_callback)
proc.run()
# Raise an exception if we didn't get a positive response back
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment