198198 vdo_pool_size:
199199 description: vdo_pool_size
200200 type: str
201+ part_type:
202+ description: part_type
203+ type: str
201204 volumes:
202205 description: volumes
203206 type: list
377380import os
378381import traceback
379382import inspect
383+ import re
380384
381385BLIVET_PACKAGE = None
382386LIB_IMP_ERR3 = ""
392396 from blivet3 .errors import RaidError
393397 from blivet3 .flags import flags as blivet_flags
394398 from blivet3 .formats import fslib , get_format
395- from blivet3 .partitioning import do_partitioning
399+ from blivet3 .partitioning import do_partitioning , parted
396400 from blivet3 .size import Size
397401 from blivet3 .udev import trigger
398402 from blivet3 .util import set_up_logging
409413 from blivet .errors import RaidError
410414 from blivet .flags import flags as blivet_flags
411415 from blivet .formats import fslib , get_format
412- from blivet .partitioning import do_partitioning
416+ from blivet .partitioning import do_partitioning , parted
413417 from blivet .size import Size
414418 from blivet .udev import trigger
415419 from blivet .util import set_up_logging
@@ -974,20 +978,65 @@ class BlivetPartitionVolume(BlivetVolume):
974978 def _type_check (self ):
975979 return self ._device .raw_device .type == 'partition'
976980
977- def _get_device_id (self ):
978- device_id = None
979- if self ._blivet_pool ._disks [0 ].partitioned and len (self ._blivet_pool ._disks [0 ].children ) == 1 :
980- device_id = self ._blivet_pool ._disks [0 ].children [0 ].name
981+ def _update_from_device (self , param_name ):
982+ """ Return True if param_name's value was retrieved from a looked-up device. """
983+ if param_name == 'part_type' :
984+ if self ._device .raw_device .is_primary :
985+ self ._volume ['part_type' ] = 'primary'
986+ elif self ._device .raw_device .is_extended :
987+ self ._volume ['part_type' ] = 'extended'
988+ elif self ._device .raw_device .is_logical :
989+ self ._volume ['part_type' ] = 'logical'
990+ elif param_name == 'fs_type' :
991+ if self ._device .raw_device .is_extended :
992+ self ._volume ['fs_type' ] = 'unformatted'
993+ else :
994+ return super (BlivetPartitionVolume , self )._update_from_device (param_name )
995+ else :
996+ return super (BlivetPartitionVolume , self )._update_from_device (param_name )
981997
982- return device_id
998+ return True
983999
984- def _resize (self ):
985- pass
1000+ def _get_part_by_partnum (self , partnum ):
1001+ return next ((p for p in self ._blivet_pool ._disks [0 ].children if (p .parted_partition and p .parted_partition .number == partnum )),
1002+ None )
1003+
1004+ def _get_device_id (self ):
1005+ name = self ._volume ['name' ]
1006+ if self ._blivet_pool ._disks [0 ].partitioned :
1007+ if name in (p .name for p in self ._blivet_pool ._disks [0 ].children ):
1008+ # partition is specified by its name, e.g. "sda1"
1009+ return name
1010+ elif name and name .isdigit ():
1011+ # partition is specified by its partition number, e.g. "1"
1012+ part = self ._get_part_by_partnum (int (name ))
1013+ if part :
1014+ return os .path .basename (part .path )
1015+ elif name and name [- 1 ].isdigit ():
1016+ # this might be something like "test1", not really supported but we used it previously
1017+ # with the "single partition spanning whole disk" approach so lets just keep this
1018+ # supported for backwards compatibility
1019+ match = re .search (r'\d+$' , name )
1020+ if match :
1021+ part = self ._get_part_by_partnum (int (match .group ()))
1022+ if part :
1023+ return os .path .basename (part .path )
1024+ return None
9861025
9871026 def _manage_cache (self ):
9881027 if self ._volume ['cached' ]:
9891028 raise BlivetAnsibleError ("caching is not supported for partition volumes" )
9901029
1030+ def _get_part_weight (self ):
1031+ # XXX make sure the newly created partitions are in right order. We use the partition
1032+ # number as weight, otherwise blivet would create the partitions in random order breaking
1033+ # the idempotency
1034+ name = self ._volume ['name' ]
1035+ match = re .search (r'\d+$' , name )
1036+ if match :
1037+ return - int (match .group ()) * 100
1038+ return 0
1039+
9911040 def _create (self ):
9921041 if self ._device :
9931042 return
@@ -1000,13 +1049,41 @@ def _create(self):
10001049 if parent is None :
10011050 raise BlivetAnsibleError ("failed to find pool '%s' for volume '%s'" % (self ._blivet_pool ['name' ], self ._volume ['name' ]))
10021051
1003- size = Size ("256 MiB" )
1004- maxsize = None
1005- if isinstance (self ._volume ['size' ], str ) and '%' in self ._volume ['size' ]:
1006- maxsize = self ._get_size ()
1052+ size = self ._get_size ()
1053+ if size == Size (0 ):
1054+ # backward compatibility with the old "single partition spanning whole disk"
1055+ # approach -- Size 0 means to use the entire disk
1056+ size = Size ("256 MiB" )
1057+ grow = True
1058+ else :
1059+ grow = False
1060+
1061+ part_type = self ._volume ['part_type' ]
1062+ if part_type == "primary" :
1063+ parted_type = parted .PARTITION_NORMAL
1064+ elif part_type == "extended" :
1065+ parted_type = parted .PARTITION_EXTENDED
1066+ elif part_type == "logical" :
1067+ parted_type = parted .PARTITION_LOGICAL
1068+ else :
1069+ parted_type = None
1070+ if part_type in ("extended" , "logical" ) and parent .format .label_type != "msdos" :
1071+ raise BlivetAnsibleError ("extended and logical partitions can be created only on MSDOS disk" )
1072+ if part_type == "extended" :
1073+ if self ._volume ['encryption' ]:
1074+ raise BlivetAnsibleError ("extended partitions cannot be encrypted" )
1075+ if self ._volume ['mount_point' ]:
1076+ raise BlivetAnsibleError ("extended partitions cannot be mounted" )
1077+ if part_type == "extended" :
1078+ fmt = None
1079+ self ._volume ['fs_type' ] = 'unformatted'
1080+ else :
1081+ fmt = self ._get_format ()
10071082
10081083 try :
1009- device = self ._blivet .new_partition (parents = [parent ], size = size , maxsize = maxsize , grow = True , fmt = self ._get_format ())
1084+ device = self ._blivet .new_partition (parents = [parent ], size = size , grow = grow , fmt = fmt ,
1085+ weight = self ._get_part_weight (),
1086+ part_type = parted_type )
10101087 except Exception :
10111088 raise BlivetAnsibleError ("failed set up volume '%s'" % self ._volume ['name' ])
10121089
@@ -1708,8 +1785,12 @@ def _type_check(self):
17081785 return self ._device .partitionable
17091786
17101787 def _look_up_device (self ):
1711- self ._look_up_disks ()
1712- self ._device = self ._disks [0 ]
1788+ device = self ._blivet .devicetree .resolve_device (self ._pool ['name' ])
1789+ if device is not None :
1790+ self ._device = device
1791+ else :
1792+ self ._look_up_disks ()
1793+ self ._device = self ._disks [0 ]
17131794
17141795 def _create (self ):
17151796 if self ._device .format .type != "disklabel" or \
@@ -2361,6 +2442,7 @@ def run_module():
23612442 cache_size = dict (type = 'str' ),
23622443 compression = dict (type = 'bool' ),
23632444 deduplication = dict (type = 'bool' ),
2445+ part_type = dict (type = 'str' ),
23642446 raid_disks = dict (type = 'list' , elements = 'str' , default = list ()),
23652447 raid_stripe_size = dict (type = 'str' ),
23662448 thin_pool_name = dict (type = 'str' ),
0 commit comments