@@ -1405,6 +1405,7 @@ class GenericHardwareManager(HardwareManager):
14051405 def __init__ (self ):
14061406 self .lldp_data = {}
14071407 self ._lshw_cache = None
1408+ self ._raid_root_device_mapping = {}
14081409
14091410 def evaluate_hardware_support (self ):
14101411 return HardwareSupport .GENERIC
@@ -1855,6 +1856,33 @@ def get_os_install_device(self, permit_refresh=False):
18551856 cached_node , all_serial_and_wwn = True )
18561857 else :
18571858 block_devices = self .list_block_devices (all_serial_and_wwn = True )
1859+ # Note(mostepha): Use the root volume from raid config if it's present
1860+ for raid_volume_name , is_root_volume in \
1861+ self ._raid_root_device_mapping .items ():
1862+ if is_root_volume :
1863+ LOG .debug ('Using root volume, %s, from target raid config.' ,
1864+ raid_volume_name )
1865+ if root_device_hints :
1866+ LOG .warning ('Both root device hints (%s) and a root '
1867+ 'volume from the target RAID configuration '
1868+ 'are defined. The RAID root volume will be '
1869+ 'used.' ,
1870+ root_device_hints )
1871+ return raid_volume_name
1872+ elif is_root_volume is False :
1873+ # NOTE(mostepha): Remove raid volumes, and related
1874+ # holder disks/partitions, where is_root_volume=false.
1875+ # This allows users to exclude RAID volumes from being
1876+ # used as the root volume.
1877+ holder_disks = get_holder_disks (raid_volume_name )
1878+ raid_partitions = get_component_devices (raid_volume_name )
1879+ LOG .debug ('Excluding %s and related holder disks/partitions, '
1880+ '(%s and %s), from possible root devices.' ,
1881+ raid_volume_name , holder_disks , raid_partitions )
1882+ block_devices = [blk_dev for blk_dev in block_devices
1883+ if blk_dev .name != raid_volume_name
1884+ and blk_dev .name not in holder_disks
1885+ and blk_dev .name not in raid_partitions ]
18581886 if not root_device_hints :
18591887 dev_name = utils .guess_root_disk (block_devices ).name
18601888 else :
@@ -3323,7 +3351,11 @@ def _determine_which_logical_disks_should_not_be_created(
33233351 # partition index for each physical device.
33243352 indices = {}
33253353 for index , logical_disk in enumerate (logical_disks ):
3326- raid_utils .create_raid_device (index , logical_disk , indices )
3354+ raid_volume = raid_utils .create_raid_device (
3355+ index , logical_disk , indices )
3356+ if logical_disk .get ('is_root_volume' ) is not None :
3357+ self ._raid_root_device_mapping [raid_volume ] = \
3358+ logical_disk .get ('is_root_volume' )
33273359
33283360 LOG .info ("Successfully created Software RAID" )
33293361
@@ -3607,6 +3639,7 @@ def validate_configuration(self, raid_config, node):
36073639
36083640 raid_skip_list = self .get_skip_list_from_node_for_raids (node )
36093641 volume_names = []
3642+ root_volume_selected = False
36103643 # All disks need to be flagged for Software RAID
36113644 for logical_disk in logical_disks :
36123645 if logical_disk .get ('controller' ) != 'software' :
@@ -3629,6 +3662,15 @@ def validate_configuration(self, raid_config, node):
36293662 else :
36303663 volume_names .append (volume_name )
36313664
3665+ is_root_volume = logical_disk .get ('is_root_volume' )
3666+ if is_root_volume :
3667+ if root_volume_selected :
3668+ msg = ("Software RAID configuration allows only one "
3669+ "logical disk to be marked as is_root_volume" )
3670+ raid_errors .append (msg )
3671+ else :
3672+ root_volume_selected = True
3673+
36323674 physical_disks = logical_disk .get ('physical_disks' )
36333675 if physical_disks is not None :
36343676 if (not isinstance (physical_disks , list )
0 commit comments