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

Added MDRAID support

parent 0fd96045
......@@ -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}')
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