Commit efd8ac3d authored by Nigel Kukard's avatar Nigel Kukard
Browse files

Merge branch 'nkupdates' into 'master'

Nkupdates

See merge request idms-linux-rolling/projects/idms-linux-installer!8
parents c0cab1c2 fb220016
......@@ -2,5 +2,5 @@ build/
.coverage
.mypy_cache
.pytest_cache
src/IDMS_Linux_Installer.egg-info
src/idmslinux_installer.egg-info
**/__pycache__/
......@@ -261,7 +261,7 @@ class Ili:
# Display a checklist with the disks on it
code, disks = self._dialog.checklist(
'Select disks to install on',
height=10, width=40, list_height=5,
height=20, width=40, list_height=10,
title='Disk Selection',
choices=[(x.path, x.size_str, False) for x in self._block_devices],
)
......@@ -290,7 +290,7 @@ class Ili:
# Display a radiolist with the disk usage strategies
code, chosen_strategy = self._dialog.radiolist(
'Select disk usage strategy',
height=10, width=40, list_height=5,
height=20, width=40, list_height=10,
title='Disk Usage Strategy',
choices=[
(x['strategy'], x['description'], 0) for x in self.state.supported_diskusage_strategies
......@@ -321,7 +321,7 @@ class Ili:
# Display a radiolist with the disk layout strategies
code, chosen_strategy = self._dialog.radiolist(
'Select disk layout strategy',
height=10, width=40, list_height=5,
height=20, width=40, list_height=10,
title='Disk Selection',
choices=[
(x['strategy'], x['description'], False) for x in self.state.supported_disklayout_strategies
......
......@@ -57,7 +57,7 @@ class DiskUsageASIS(Plugin):
sfdisk.create_partition(-1, 500, 'EFI System')
sfdisk.create_partition(-1, 500, 'Linux filesystem')
sfdisk.create_partition(-1, -1, 'Linux filesystem')
sfdisk.write_partitions(disk)
sfdisk.write_partitions(disk, output_callback=ili_state.output_callback)
# Add the block devices to the installer
ili_state.output_callback('Adding block devices')
......
......@@ -15,10 +15,13 @@
"""MDRAID disk usage strategies."""
import re
from typing import List
from idmslinux_installer.ilistate import IliState
from idmslinux_installer.plugin import Plugin
from idmslinux_installer.util.mdadm import Mdadm
from idmslinux_installer.util.sfdisk import Sfdisk
# Ignore warning that we have not overridden all base class methods.
......@@ -52,3 +55,62 @@ class DiskUsageMDRAID(Plugin):
# If we have 4 or more disks, and they are in multiples of 2, then RAID10 will work
if (disk_count >= 4) & (disk_count % 2 == 0):
ili_state.add_diskusage_strategy('MDRAID10', 'Setup MDRAID10')
def commit_diskusage_strategy(self, ili_state: IliState):
"""Commit disk usage strategy and return the root, boot and efi device."""
raid_level = None
# Check the strategy to use for these disks
if ili_state.diskusage_strategy in ['MDRAID1', 'MDRAID5', 'MDRAID6', 'MDRAID10']:
ili_state.output_callback('Partitioning disk')
# Create an Sfdisk object
sfdisk = Sfdisk()
# Add disk partitions
sfdisk.create_partition(-1, 1, 'BIOS boot')
sfdisk.create_partition(-1, 500, 'EFI System')
sfdisk.create_partition(-1, 500, 'Linux filesystem')
sfdisk.create_partition(-1, -1, 'Linux filesystem')
# Partition all disks
for disk in ili_state.install_disks:
sfdisk.write_partitions(disk, output_callback=ili_state.output_callback)
matches = re.match(r'^MDRAID(?P<raid_level>\d+)', ili_state.diskusage_strategy)
if not matches:
raise RuntimeError(f'Failed to determine RAID level from "{ili_state.diskusage_strategy}"')
raid_level = int(matches.group('raid_level'))
# We will have a level here if we're creating a RAID level we understand
if raid_level:
ili_state.output_callback('Creating MDRAID arrays')
efi_disk = ili_state.install_disks[0]
boot_disk = '/dev/md/0'
root_disk = '/dev/md/1'
mdadm = Mdadm()
# Add all part3 to array
mdadm.create(boot_disk, 1, [f'{x}3' for x in ili_state.install_disks],
output_callback=ili_state.output_callback)
# Add all part4 partitions to array
mdadm.create(root_disk, raid_level, [f'{x}4' for x in ili_state.install_disks],
output_callback=ili_state.output_callback)
# Add the block devices to the installer
ili_state.output_callback('Adding block devices')
ili_state.add_blockdevice('efi', f'{efi_disk}2')
ili_state.add_blockdevice('boot', f'{boot_disk}')
ili_state.add_blockdevice('root', f'{root_disk}')
# Add the MBR device to the installer
ili_state.output_callback('Adding device for MBR')
for disk in ili_state.install_disks:
ili_state.add_boot_mbr(disk)
# Add mdadm to the base packages
ili_state.add_base_package('mdadm')
# Copyright (c) 2019, AllWorldIT
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
"""Support class for mdadm."""
from typing import List
from idmslinux_installer.util.asyncsubprocess import (AsyncSubprocess,
OutputCallback)
class Mdadm:
"""The Mdadm class handles our interface to mdadm."""
def __init__(self, load: bool = True):
"""Initialize our class and load system partition types."""
def create(self, md_device: str, level: int, devices: List[str], output_callback: OutputCallback = None):
"""Create RAID device."""
# If we didn't get an output_callback, set it to our own class method
if not output_callback:
output_callback = self._default_output_callback
# Work out how many devices we have
num_devices = len(devices)
# Run mdadm
proc = AsyncSubprocess(['mdadm', '--create', md_device, '--level', str(level), '--raid-devices', str(num_devices),
'--metadata', 'default', *devices], output_callback=output_callback)
proc.run()
# Raise an exception if we didn't get a positive response back
if proc.retcode != 0:
raise OSError(f'Failed to create md device {md_device} return code {proc.retcode}')
def _default_output_callback(self, line: str):
line.rstrip()
print(f'grub: {line}')
......@@ -19,7 +19,8 @@ import re
import subprocess
from typing import Dict, List
from idmslinux_installer.util.asyncsubprocess import AsyncSubprocess
from idmslinux_installer.util.asyncsubprocess import (AsyncSubprocess,
OutputCallback)
class Sfdisk:
......@@ -76,9 +77,13 @@ class Sfdisk:
'type': part_type,
})
def write_partitions(self, device: str):
def write_partitions(self, device: str, output_callback: OutputCallback = None):
"""Write out partitions to a disk device."""
# If we didn't get an output_callback, set it to our own class method
if not output_callback:
output_callback = self._default_output_callback
# Generate partition lines
partition_lines: List[str] = [
'%s,%s,%s\n' % (_sanitize_parm(x['start']), _sanitize_parm(x['size']), self.partition_types[x['type']])
......@@ -86,14 +91,18 @@ class Sfdisk:
]
# Run sfdisk
proc = AsyncSubprocess(['sfdisk', '--wipe', 'always', '--label', 'gpt', device],
input_lines=partition_lines)
proc = AsyncSubprocess(['sfdisk', '--wipe', 'always', '--wipe-partitions', 'always', '--label', 'gpt', device],
input_lines=partition_lines, output_callback=output_callback)
proc.run()
# Raise an exception if we didn't get a positive response back
if proc.retcode != 0:
raise OSError(f'Failed to write partitions to device {device} return code {proc.retcode}')
def _default_output_callback(self, line: str):
line.rstrip()
print(f'grub: {line}')
def _sanitize_parm(pos: int) -> str:
"""Sanitize sfdisk start/size parameter."""
......
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