Source code for kiwi.storage.raid_device

# Copyright (c) 2015 SUSE Linux GmbH.  All rights reserved.
#
# This file is part of kiwi.
#
# kiwi 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.
#
# kiwi 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 kiwi.  If not, see <http://www.gnu.org/licenses/>
#
import os
import logging
from typing import Optional

# project
from kiwi.command import Command
from kiwi.storage.device_provider import DeviceProvider
from kiwi.storage.mapped_device import MappedDevice

from kiwi.exceptions import (
    KiwiRaidSetupError
)

log = logging.getLogger('kiwi')


[docs] class RaidDevice(DeviceProvider): """ **Implement raid setup on a storage device** :param object storage_provider: Instance of class based on DeviceProvider """ def __init__(self, storage_provider: DeviceProvider): #: the underlaying device provider self.storage_provider = storage_provider self.raid_level_map = { 'mirroring': '1', 'striping': '0' } self.raid_device = None def __enter__(self): return self
[docs] def get_device(self) -> Optional[MappedDevice]: """ Instance of MappedDevice providing the raid device :return: mapped raid device :rtype: MappedDevice """ if self.raid_device: return MappedDevice( device=self.raid_device, device_provider=self ) return None
[docs] def create_degraded_raid(self, raid_level): """ Create a raid array in degraded mode with one device missing. This only works in the raid levels 0(striping) and 1(mirroring) :param string raid_level: raid level name """ if raid_level not in self.raid_level_map: raise KiwiRaidSetupError( 'Only raid levels 0(striping) and 1(mirroring) are supported' ) raid_device = None for raid_id in range(9): raid_device = '/dev/md' + format(raid_id) if os.path.exists(raid_device): raid_device = None else: break if not raid_device: raise KiwiRaidSetupError( 'Could not find free raid device in range md0-8' ) log.info( 'Creating raid array in %s mode as %s', raid_level, raid_device ) Command.run( [ 'mdadm', '--create', '--run', raid_device, '--level', self.raid_level_map[raid_level], '--raid-disks', '2', self.storage_provider.get_device(), 'missing' ] ) self.raid_device = raid_device
[docs] def create_raid_config(self, filename: str) -> None: """ Create mdadm config file from mdadm request :param string filename: config file name """ if not self.raid_device: raise KiwiRaidSetupError("No raid device defined, cannot create raid config!") mdadm_call = Command.run( ['mdadm', '-Db', self.raid_device] ) with open(filename, 'w') as mdadmconf: mdadmconf.write(mdadm_call.output)
[docs] def is_loop(self) -> bool: """ Check if storage provider is loop based Return loop status from base storage provider :return: True or False :rtype: bool """ return self.storage_provider.is_loop()
def __exit__(self, exc_type, exc_value, traceback): if self.raid_device: try: Command.run( ['mdadm', '--stop', self.raid_device] ) except Exception as issue: log.error( 'Shutdown of raid device {0} failed with: {1}'.format( self.raid_device, issue ) )