From 0a69c057b41890d3d426ac10dfc198e7a3dbab4e Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Wed, 3 Mar 2021 07:55:20 -0700 Subject: [PATCH] resolve ansible-test issues This fixes many formatting issues as well to make black, flake8, pylint, yamllint, and ansible-lint happier. --- .github/workflows/tox.yml | 4 +- .sanity-ansible-ignore-2.9.txt | 13 + library/blivet.py | 968 +++++++++++------- library/blockdev_info.py | 45 +- library/bsize.py | 56 +- library/find_unused_disk.py | 101 +- library/lvm_gensym.py | 119 ++- library/resolve_blockdev.py | 71 +- module_utils/storage_lsr/size.py | 86 +- tests/setup_module_utils.sh | 41 - tests/test-verify-volume-device.yml | 4 +- tests/test-verify-volume-md.yml | 2 +- tests/test.yml | 2 +- tests/tests_create_lv_size_equal_to_vg.yml | 28 +- ...ts_create_partition_volume_then_remove.yml | 4 +- tests/tests_existing_lvm_pool.yml | 12 +- tests/tests_lvm_auto_size_cap.yml | 42 +- tests/tests_lvm_one_disk_one_volume.yml | 46 +- tests/tests_misc.yml | 2 +- tests/tests_null_raid_pool.yml | 14 +- tests/tests_resize.yml | 86 +- tests/unit/bsize_test.py | 5 + tests/unit/gensym_test.py | 103 +- tests/unit/resolve_blockdev_test.py | 74 +- tests/unit/test_unused_disk.py | 73 +- tox.ini | 6 - 26 files changed, 1177 insertions(+), 830 deletions(-) create mode 100644 .sanity-ansible-ignore-2.9.txt delete mode 100755 tests/setup_module_utils.sh diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index eceb71f..ec3ec9f 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -3,7 +3,7 @@ name: tox on: # yamllint disable-line rule:truthy - pull_request env: - TOX_LSR: "git+https://github.com/linux-system-roles/tox-lsr@2.2.0" + TOX_LSR: "git+https://github.com/linux-system-roles/tox-lsr@2.3.0" LSR_ANSIBLES: 'ansible==2.8.* ansible==2.9.*' LSR_MSCENARIOS: default # LSR_EXTRA_PACKAGES: libdbus-1-dev @@ -36,7 +36,7 @@ jobs: toxenvs="py${toxpyver}" case "$toxpyver" in 27) toxenvs="${toxenvs},coveralls,flake8,pylint,custom" ;; - 36) toxenvs="${toxenvs},coveralls,black,yamllint,ansible-lint,shellcheck,custom,collection" ;; + 36) toxenvs="${toxenvs},coveralls,black,yamllint,ansible-lint,shellcheck,custom,collection,ansible-test" ;; 37) toxenvs="${toxenvs},coveralls,custom" ;; 38) toxenvs="${toxenvs},coveralls,custom" ;; esac diff --git a/.sanity-ansible-ignore-2.9.txt b/.sanity-ansible-ignore-2.9.txt new file mode 100644 index 0000000..bf700c6 --- /dev/null +++ b/.sanity-ansible-ignore-2.9.txt @@ -0,0 +1,13 @@ +plugins/modules/blivet.py import-2.7!skip +plugins/modules/blivet.py import-3.5!skip +plugins/modules/blivet.py import-3.6!skip +plugins/modules/blivet.py import-3.7!skip +plugins/modules/blivet.py import-3.8!skip +tests/storage/unit/gensym_test.py shebang!skip +plugins/modules/blivet.py validate-modules:import-error +plugins/modules/blivet.py validate-modules:missing-gplv3-license +plugins/modules/blockdev_info.py validate-modules:missing-gplv3-license +plugins/modules/bsize.py validate-modules:missing-gplv3-license +plugins/modules/find_unused_disk.py validate-modules:missing-gplv3-license +plugins/modules/lvm_gensym.py validate-modules:missing-gplv3-license +plugins/modules/resolve_blockdev.py validate-modules:missing-gplv3-license diff --git a/library/blivet.py b/library/blivet.py index 946b640..0e0b30c 100644 --- a/library/blivet.py +++ b/library/blivet.py @@ -1,12 +1,16 @@ #!/usr/bin/python +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", } -DOCUMENTATION = ''' +DOCUMENTATION = """ --- module: blivet @@ -15,6 +19,7 @@ short_description: Module for management of linux block device stacks version_added: "2.5" description: + - "WARNING: Do not use this module directly! It is only for role internal use." - "Module configures storage pools and volumes to match the state specified in input parameters. It does not do any management of /etc/fstab entries." @@ -30,7 +35,8 @@ options: - boolean indicating whether to create partitions on disks for pool backing devices disklabel_type: description: - - disklabel type string (eg: 'gpt') to use, overriding the built-in logic in blivet + - | + disklabel type string (eg: 'gpt') to use, overriding the built-in logic in blivet safe_mode: description: - boolean indicating that we should fail rather than implicitly/automatically @@ -41,10 +47,10 @@ options: when creating a disk volume (that is, a whole disk filesystem) author: - - David Lehman (dlehman@redhat.com) -''' + - David Lehman (@dwlehman) +""" -EXAMPLES = ''' +EXAMPLES = """ - name: Manage devices blivet: @@ -64,28 +70,40 @@ EXAMPLES = ''' mount_point: /whole_disk1 fs_type: ext4 mount_options: journal_checksum,async,noexec -''' +""" -RETURN = ''' +RETURN = """ actions: description: list of dicts describing actions taken - type: list of dict + returned: success + type: list + elements: dict leaves: description: list of paths to leaf devices - type: list of str + returned: success + type: list + elements: dict mounts: description: list of dicts describing mounts to set up - type: list of dict + returned: success + type: list + elements: dict crypts: description: list of dicts describing crypttab entries to set up - type: list of dict + returned: success + type: list + elements: dict pools: description: list of dicts describing the pools w/ device path for each volume - type: list of dict + returned: success + type: list + elements: dict volumes: description: list of dicts describing the volumes w/ device path for each - type: list of dict -''' + returned: success + type: list + elements: dict +""" import logging import os @@ -106,7 +124,8 @@ try: from blivet3.size import Size from blivet3.udev import trigger from blivet3.util import set_up_logging - BLIVET_PACKAGE = 'blivet3' + + BLIVET_PACKAGE = "blivet3" except ImportError: LIB_IMP_ERR3 = traceback.format_exc() try: @@ -119,7 +138,8 @@ except ImportError: from blivet.size import Size from blivet.udev import trigger from blivet.util import set_up_logging - BLIVET_PACKAGE = 'blivet' + + BLIVET_PACKAGE = "blivet" except ImportError: LIB_IMP_ERR = traceback.format_exc() @@ -135,23 +155,23 @@ MAX_TRIM_PERCENT = 2 use_partitions = None # create partitions on pool backing device disks? disklabel_type = None # user-specified disklabel type -safe_mode = None # do not remove any existing devices or formatting +safe_mode = None # do not remove any existing devices or formatting pool_defaults = dict() volume_defaults = dict() def find_duplicate_names(dicts): - """ Return a list of names that appear more than once in a list of dicts. + """Return a list of names that appear more than once in a list of dicts. - Items can be a list of any dicts with a 'name' key; that's all we're - looking at. """ + Items can be a list of any dicts with a 'name' key; that's all we're + looking at.""" names = list() duplicates = list() for item in dicts: - if item['name'] in names and item['name'] not in duplicates: - duplicates.append(item['name']) + if item["name"] in names and item["name"] not in duplicates: + duplicates.append(item["name"]) else: - names.append(item['name']) + names.append(item["name"]) return duplicates @@ -177,41 +197,54 @@ class BlivetBase(object): global safe_mode ret = device # Make sure to handle adjusting both existing stacks and future stacks. - if device == device.raw_device and self._spec_dict['encryption']: + if device == device.raw_device and self._spec_dict["encryption"]: # add luks luks_name = "luks-%s" % device._name - if safe_mode and (device.original_format.type is not None or - device.original_format.name != get_format(None).name): - raise BlivetAnsibleError("cannot remove existing formatting on device '%s' in safe mode due to adding encryption" % - device._name) + if safe_mode and ( + device.original_format.type is not None + or device.original_format.name != get_format(None).name + ): + raise BlivetAnsibleError( + "cannot remove existing formatting on device '%s' in safe mode due to adding encryption" + % device._name + ) if not device.format.exists: fmt = device.format else: fmt = get_format(None) - self._blivet.format_device(device, - get_format("luks", - name=luks_name, - cipher=self._spec_dict.get('encryption_cipher'), - key_size=self._spec_dict.get('encryption_key_size'), - luks_version=self._spec_dict.get('encryption_luks_version'), - passphrase=self._spec_dict.get('encryption_password') or None, - key_file=self._spec_dict.get('encryption_key') or None)) + self._blivet.format_device( + device, + get_format( + "luks", + name=luks_name, + cipher=self._spec_dict.get("encryption_cipher"), + key_size=self._spec_dict.get("encryption_key_size"), + luks_version=self._spec_dict.get("encryption_luks_version"), + passphrase=self._spec_dict.get("encryption_password") or None, + key_file=self._spec_dict.get("encryption_key") or None, + ), + ) if not device.format.has_key: - raise BlivetAnsibleError("encrypted %s '%s' missing key/password" % (self._type, self._spec_dict['name'])) + raise BlivetAnsibleError( + "encrypted %s '%s' missing key/password" + % (self._type, self._spec_dict["name"]) + ) - luks_device = devices.LUKSDevice(luks_name, - fmt=fmt, - parents=[device]) + luks_device = devices.LUKSDevice(luks_name, fmt=fmt, parents=[device]) self._blivet.create_device(luks_device) ret = luks_device - elif device != device.raw_device and not self._spec_dict['encryption']: + elif device != device.raw_device and not self._spec_dict["encryption"]: # remove luks - if safe_mode and (device.original_format.type is not None or - device.original_format.name != get_format(None).name): - raise BlivetAnsibleError("cannot remove existing formatting on device '%s' in safe mode due to encryption removal" % - device._name) + if safe_mode and ( + device.original_format.type is not None + or device.original_format.name != get_format(None).name + ): + raise BlivetAnsibleError( + "cannot remove existing formatting on device '%s' in safe mode due to encryption removal" + % device._name + ) if not device.format.exists: fmt = device.format else: @@ -240,12 +273,21 @@ class BlivetBase(object): requested_spares = self._spec_dict.get("raid_spare_count") if requested_actives is not None and requested_spares is not None: - if (requested_actives + requested_spares != len(members) or - requested_actives < 0 or requested_spares < 0): - raise BlivetAnsibleError("failed to set up '%s': cannot create RAID " - "with %s members (%s active and %s spare)" - % (self._spec_dict["name"], len(members), - requested_actives, requested_spares)) + if ( + requested_actives + requested_spares != len(members) + or requested_actives < 0 + or requested_spares < 0 + ): + raise BlivetAnsibleError( + "failed to set up '%s': cannot create RAID " + "with %s members (%s active and %s spare)" + % ( + self._spec_dict["name"], + len(members), + requested_actives, + requested_spares, + ) + ) if requested_actives is not None: active_count = requested_actives @@ -264,16 +306,20 @@ class BlivetBase(object): raise BlivetAnsibleError("chunk size must be multiple of 4 KiB") try: - raid_array = self._blivet.new_mdarray(name=raid_name, - level=self._spec_dict["raid_level"], - member_devices=active_count, - total_devices=len(members), - parents=members, - chunk_size=chunk_size, - metadata_version=self._spec_dict.get("raid_metadata_version"), - fmt=self._get_format()) + raid_array = self._blivet.new_mdarray( + name=raid_name, + level=self._spec_dict["raid_level"], + member_devices=active_count, + total_devices=len(members), + parents=members, + chunk_size=chunk_size, + metadata_version=self._spec_dict.get("raid_metadata_version"), + fmt=self._get_format(), + ) except ValueError as e: - raise BlivetAnsibleError("cannot create RAID '%s': %s" % (raid_name, str(e))) + raise BlivetAnsibleError( + "cannot create RAID '%s': %s" % (raid_name, str(e)) + ) return raid_array @@ -298,17 +344,18 @@ class BlivetVolume(BlivetBase): if self.__class__.blivet_device_class is not None: packages.extend(self.__class__.blivet_device_class._packages) - fmt = get_format(self._volume.get('fs_type')) + fmt = get_format(self._volume.get("fs_type")) packages.extend(fmt.packages) - if self._volume.get('encryption'): - packages.extend(get_format('luks').packages) + if self._volume.get("encryption"): + packages.extend(get_format("luks").packages) return packages @property def ultimately_present(self): """ Should this volume be present when we are finished? """ - return (self._volume.get('state', 'present') == 'present' and - (self._blivet_pool is None or self._blivet_pool.ultimately_present)) + return self._volume.get("state", "present") == "present" and ( + self._blivet_pool is None or self._blivet_pool.ultimately_present + ) def _type_check(self): # pylint: disable=no-self-use """ Is self._device of the correct type? """ @@ -316,7 +363,7 @@ class BlivetVolume(BlivetBase): def _get_device_id(self): """ Return an identifier by which to try looking the volume up. """ - return self._volume['name'] + return self._volume["name"] def _look_up_device(self): """ Try to look up this volume in blivet's device tree. """ @@ -331,14 +378,14 @@ class BlivetVolume(BlivetBase): if device is None: return - if device.format.type == 'luks': + if device.format.type == "luks": # XXX If we have no key we will always re-encrypt. - device.format._key_file = self._volume.get('encryption_key') - device.format.passphrase = self._volume.get('encryption_password') + device.format._key_file = self._volume.get("encryption_key") + device.format.passphrase = self._volume.get("encryption_password") # set up the original format as well since it'll get used for processing - device.original_format._key_file = self._volume.get('encryption_key') - device.original_format.passphrase = self._volume.get('encryption_password') + device.original_format._key_file = self._volume.get("encryption_key") + device.original_format.passphrase = self._volume.get("encryption_password") if device.isleaf: self._blivet.populate() @@ -361,26 +408,31 @@ class BlivetVolume(BlivetBase): elif encrypted: luks_fmt = self._device.format - if param_name == 'size': - self._volume['size'] = int(self._device.size.convert_to()) - elif param_name == 'fs_type' and (self._device.format.type or self._device.format.name != get_format(None).name): - self._volume['fs_type'] = self._device.format.type - elif param_name == 'fs_label': - self._volume['fs_label'] = getattr(self._device.format, 'label', "") or "" - elif param_name == 'mount_point': - self._volume['mount_point'] = getattr(self._device.format, 'mountpoint', None) - elif param_name == 'disks': - self._volume['disks'] = [d.name for d in self._device.disks] - elif param_name == 'encryption': - self._volume['encryption'] = encrypted - elif param_name == 'encryption_key_size' and encrypted: - self._volume['encryption_key_size'] = luks_fmt.key_size - elif param_name == 'encryption_key_file' and encrypted: - self._volume['encryption_key_file'] = luks_fmt.key_file - elif param_name == 'encryption_cipher' and encrypted: - self._volume['encryption_cipher'] = luks_fmt.cipher - elif param_name == 'encryption_luks_version' and encrypted: - self._volume['encryption_luks_version'] = luks_fmt.luks_version + if param_name == "size": + self._volume["size"] = int(self._device.size.convert_to()) + elif param_name == "fs_type" and ( + self._device.format.type + or self._device.format.name != get_format(None).name + ): + self._volume["fs_type"] = self._device.format.type + elif param_name == "fs_label": + self._volume["fs_label"] = getattr(self._device.format, "label", "") or "" + elif param_name == "mount_point": + self._volume["mount_point"] = getattr( + self._device.format, "mountpoint", None + ) + elif param_name == "disks": + self._volume["disks"] = [d.name for d in self._device.disks] + elif param_name == "encryption": + self._volume["encryption"] = encrypted + elif param_name == "encryption_key_size" and encrypted: + self._volume["encryption_key_size"] = luks_fmt.key_size + elif param_name == "encryption_key_file" and encrypted: + self._volume["encryption_key_file"] = luks_fmt.key_file + elif param_name == "encryption_cipher" and encrypted: + self._volume["encryption_cipher"] = luks_fmt.cipher + elif param_name == "encryption_luks_version" and encrypted: + self._volume["encryption_luks_version"] = luks_fmt.luks_version else: return False @@ -392,7 +444,7 @@ class BlivetVolume(BlivetBase): if name in self._volume: continue - default = None if default in ('none', 'None', 'null') else default + default = None if default in ("none", "None", "null") else default if self._device: # Apply values from the device if it already exists. @@ -403,12 +455,17 @@ class BlivetVolume(BlivetBase): def _get_format(self): """ Return a blivet.formats.DeviceFormat instance for this volume. """ - fmt = get_format(self._volume['fs_type'], - mountpoint=self._volume.get('mount_point'), - label=self._volume['fs_label'], - create_options=self._volume['fs_create_options']) + fmt = get_format( + self._volume["fs_type"], + mountpoint=self._volume.get("mount_point"), + label=self._volume["fs_label"], + create_options=self._volume["fs_create_options"], + ) if not fmt.supported or not fmt.formattable: - raise BlivetAnsibleError("required tools for file system '%s' are missing" % self._volume['fs_type']) + raise BlivetAnsibleError( + "required tools for file system '%s' are missing" + % self._volume["fs_type"] + ) return fmt @@ -422,9 +479,9 @@ class BlivetVolume(BlivetBase): return # save device identifiers for use by the role - self._volume['_device'] = self._device.path - self._volume['_raw_device'] = self._device.raw_device.path - self._volume['_mount_id'] = self._device.fstab_spec + self._volume["_device"] = self._device.path + self._volume["_raw_device"] = self._device.raw_device.path + self._volume["_mount_id"] = self._device.fstab_spec # schedule removal of this device and any descendant devices self._blivet.devicetree.recursive_remove(self._device.raw_device) @@ -435,9 +492,12 @@ class BlivetVolume(BlivetBase): def _resize(self): """ Schedule actions as needed to ensure the device has the desired size. """ try: - size = Size(self._volume['size']) + size = Size(self._volume["size"]) except Exception: - raise BlivetAnsibleError("invalid size specification for volume '%s': '%s'" % (self._volume['name'], self._volume['size'])) + raise BlivetAnsibleError( + "invalid size specification for volume '%s': '%s'" + % (self._volume["name"], self._volume["size"]) + ) if size and self._device.size != size: try: @@ -448,28 +508,44 @@ class BlivetVolume(BlivetBase): if not self._device.resizable: return - trim_percent = (1.0 - float(self._device.max_size / size))*100 - log.debug("resize: size=%s->%s ; trim=%s", self._device.size, size, trim_percent) + trim_percent = (1.0 - float(self._device.max_size / size)) * 100 + log.debug( + "resize: size=%s->%s ; trim=%s", self._device.size, size, trim_percent + ) if size > self._device.max_size and trim_percent <= MAX_TRIM_PERCENT: - log.info("adjusting %s resize target from %s to %s to fit in free space", - self._volume['name'], - size, - self._device.max_size) + log.info( + "adjusting %s resize target from %s to %s to fit in free space", + self._volume["name"], + size, + self._device.max_size, + ) size = self._device.max_size if size == self._device.size: return if not self._device.min_size <= size <= self._device.max_size: - raise BlivetAnsibleError("volume '%s' cannot be resized to '%s'" % (self._volume['name'], size)) + raise BlivetAnsibleError( + "volume '%s' cannot be resized to '%s'" + % (self._volume["name"], size) + ) try: self._blivet.resize_device(self._device, size) except ValueError as e: - raise BlivetAnsibleError("volume '%s' cannot be resized from %s to %s: %s" % (self._device.name, - self._device.size, - size, str(e))) - elif size and self._device.exists and self._device.size != size and not self._device.resizable: - raise BlivetAnsibleError("volume '%s' cannot be resized from %s to %s" % (self._device.name, self._device.size, size)) + raise BlivetAnsibleError( + "volume '%s' cannot be resized from %s to %s: %s" + % (self._device.name, self._device.size, size, str(e)) + ) + elif ( + size + and self._device.exists + and self._device.size != size + and not self._device.resizable + ): + raise BlivetAnsibleError( + "volume '%s' cannot be resized from %s to %s" + % (self._device.name, self._device.size, size) + ) def _reformat(self): """ Schedule actions as needed to ensure the volume is formatted as specified. """ @@ -477,10 +553,18 @@ class BlivetVolume(BlivetBase): if self._device.format.type == fmt.type: return - if safe_mode and (self._device.format.type is not None or self._device.format.name != get_format(None).name): - raise BlivetAnsibleError("cannot remove existing formatting on volume '%s' in safe mode" % self._volume['name']) - - if self._device.format.status and (self._device.format.mountable or self._device.format.type == "swap"): + if safe_mode and ( + self._device.format.type is not None + or self._device.format.name != get_format(None).name + ): + raise BlivetAnsibleError( + "cannot remove existing formatting on volume '%s' in safe mode" + % self._volume["name"] + ) + + if self._device.format.status and ( + self._device.format.mountable or self._device.format.type == "swap" + ): self._device.format.teardown() if not self._device.isleaf: self._blivet.devicetree.recursive_remove(self._device, remove_device=False) @@ -503,7 +587,9 @@ class BlivetVolume(BlivetBase): # at this point we should have a blivet.devices.StorageDevice instance if self._device is None: - raise BlivetAnsibleError("failed to look up or create device '%s'" % self._volume['name']) + raise BlivetAnsibleError( + "failed to look up or create device '%s'" % self._volume["name"] + ) self._manage_encryption() @@ -511,24 +597,31 @@ class BlivetVolume(BlivetBase): if self._device.raw_device.exists: self._reformat() - if self.ultimately_present and self._volume['mount_point'] and not self._device.format.mountable: - raise BlivetAnsibleError("volume '%s' has a mount point but no mountable file system" % self._volume['name']) + if ( + self.ultimately_present + and self._volume["mount_point"] + and not self._device.format.mountable + ): + raise BlivetAnsibleError( + "volume '%s' has a mount point but no mountable file system" + % self._volume["name"] + ) # schedule resize if appropriate - if self._device.raw_device.exists and self._volume['size']: + if self._device.raw_device.exists and self._volume["size"]: self._resize() # save device identifiers for use by the role - self._volume['_device'] = self._device.path - self._volume['_raw_device'] = self._device.raw_device.path - self._volume['_mount_id'] = self._device.fstab_spec + self._volume["_device"] = self._device.path + self._volume["_raw_device"] = self._device.raw_device.path + self._volume["_mount_id"] = self._device.fstab_spec class BlivetDiskVolume(BlivetVolume): blivet_device_class = devices.DiskDevice def _get_device_id(self): - return self._volume['disks'][0] + return self._volume["disks"][0] def _type_check(self): return self._device.raw_device.is_disk @@ -536,7 +629,7 @@ class BlivetDiskVolume(BlivetVolume): def _get_format(self): fmt = super(BlivetDiskVolume, self)._get_format() # pass -F to mke2fs on whole disks in RHEL7 - mkfs_options = diskvolume_mkfs_option_map.get(self._volume['fs_type']) + mkfs_options = diskvolume_mkfs_option_map.get(self._volume["fs_type"]) if mkfs_options: if fmt.create_options: fmt.create_options += " " @@ -552,23 +645,31 @@ class BlivetDiskVolume(BlivetVolume): def _look_up_device(self): super(BlivetDiskVolume, self)._look_up_device() if not self._get_device_id(): - raise BlivetAnsibleError("no disks specified for volume '%s'" % self._volume['name']) - elif not isinstance(self._volume['disks'], list): + raise BlivetAnsibleError( + "no disks specified for volume '%s'" % self._volume["name"] + ) + elif not isinstance(self._volume["disks"], list): raise BlivetAnsibleError("volume disks must be specified as a list") if self._device is None: - raise BlivetAnsibleError("unable to resolve disk specified for volume '%s' (%s)" % (self._volume['name'], self._volume['disks'])) + raise BlivetAnsibleError( + "unable to resolve disk specified for volume '%s' (%s)" + % (self._volume["name"], self._volume["disks"]) + ) class BlivetPartitionVolume(BlivetVolume): blivet_device_class = devices.PartitionDevice def _type_check(self): - return self._device.raw_device.type == 'partition' + return self._device.raw_device.type == "partition" def _get_device_id(self): device_id = None - if self._blivet_pool._disks[0].partitioned and len(self._blivet_pool._disks[0].children) == 1: + if ( + self._blivet_pool._disks[0].partitioned + and len(self._blivet_pool._disks[0].children) == 1 + ): device_id = self._blivet_pool._disks[0].children[0].name return device_id @@ -583,22 +684,29 @@ class BlivetPartitionVolume(BlivetVolume): if self._blivet_pool: parent = self._blivet_pool._device else: - parent = self._blivet.devicetree.resolve_device(self._volume['pool']) + parent = self._blivet.devicetree.resolve_device(self._volume["pool"]) if parent is None: - raise BlivetAnsibleError("failed to find pool '%s' for volume '%s'" % (self._blivet_pool['name'], self._volume['name'])) + raise BlivetAnsibleError( + "failed to find pool '%s' for volume '%s'" + % (self._blivet_pool["name"], self._volume["name"]) + ) size = Size("256 MiB") try: - device = self._blivet.new_partition(parents=[parent], size=size, grow=True, fmt=self._get_format()) + device = self._blivet.new_partition( + parents=[parent], size=size, grow=True, fmt=self._get_format() + ) except Exception: - raise BlivetAnsibleError("failed set up volume '%s'" % self._volume['name']) + raise BlivetAnsibleError("failed set up volume '%s'" % self._volume["name"]) self._blivet.create_device(device) try: do_partitioning(self._blivet) except Exception: - raise BlivetAnsibleError("partition allocation failed for volume '%s'" % self._volume['name']) + raise BlivetAnsibleError( + "partition allocation failed for volume '%s'" % self._volume["name"] + ) self._device = device @@ -609,7 +717,7 @@ class BlivetLVMVolume(BlivetVolume): def _get_device_id(self): if not self._blivet_pool._device: return None - return "%s-%s" % (self._blivet_pool._device.name, self._volume['name']) + return "%s-%s" % (self._blivet_pool._device.name, self._volume["name"]) def _create(self): if self._device: @@ -617,51 +725,75 @@ class BlivetLVMVolume(BlivetVolume): parent = self._blivet_pool._device if parent is None: - raise BlivetAnsibleError("failed to find pool '%s' for volume '%s'" % (self._blivet_pool['name'], self._volume['name'])) + raise BlivetAnsibleError( + "failed to find pool '%s' for volume '%s'" + % (self._blivet_pool["name"], self._volume["name"]) + ) try: - size = Size(self._volume['size']) + size = Size(self._volume["size"]) except Exception: - raise BlivetAnsibleError("invalid size '%s' specified for volume '%s'" % (self._volume['size'], self._volume['name'])) + raise BlivetAnsibleError( + "invalid size '%s' specified for volume '%s'" + % (self._volume["size"], self._volume["name"]) + ) fmt = self._get_format() - trim_percent = (1.0 - float(parent.free_space / size))*100 + trim_percent = (1.0 - float(parent.free_space / size)) * 100 log.debug("size: %s ; %s", size, trim_percent) if size > parent.free_space: if trim_percent > MAX_TRIM_PERCENT: - raise BlivetAnsibleError("specified size for volume '%s' exceeds available space in pool '%s' (%s)" - % (size, parent.name, parent.free_space)) + raise BlivetAnsibleError( + "specified size for volume '%s' exceeds available space in pool '%s' (%s)" + % (size, parent.name, parent.free_space) + ) else: - log.info("adjusting %s size from %s to %s to fit in %s free space", self._volume['name'], - size, - parent.free_space, - parent.name) + log.info( + "adjusting %s size from %s to %s to fit in %s free space", + self._volume["name"], + size, + parent.free_space, + parent.name, + ) size = parent.free_space try: - device = self._blivet.new_lv(name=self._volume['name'], - parents=[parent], size=size, fmt=fmt) + device = self._blivet.new_lv( + name=self._volume["name"], parents=[parent], size=size, fmt=fmt + ) except Exception as e: - raise BlivetAnsibleError("failed to set up volume '%s': %s" % (self._volume['name'], str(e))) + raise BlivetAnsibleError( + "failed to set up volume '%s': %s" % (self._volume["name"], str(e)) + ) self._blivet.create_device(device) self._device = device class BlivetMDRaidVolume(BlivetVolume): - - def _process_device_numbers(self, members_count, requested_actives, requested_spares): + def _process_device_numbers( + self, members_count, requested_actives, requested_spares + ): active_count = members_count spare_count = 0 if requested_actives is not None and requested_spares is not None: - if (requested_actives + requested_spares != members_count or - requested_actives < 0 or requested_spares < 0): - raise BlivetAnsibleError("failed to set up volume '%s': cannot create RAID " - "with %s members (%s active and %s spare)" - % (self._volume['name'], members_count, - requested_actives, requested_spares)) + if ( + requested_actives + requested_spares != members_count + or requested_actives < 0 + or requested_spares < 0 + ): + raise BlivetAnsibleError( + "failed to set up volume '%s': cannot create RAID " + "with %s members (%s active and %s spare)" + % ( + self._volume["name"], + members_count, + requested_actives, + requested_spares, + ) + ) if requested_actives is not None: active_count = requested_actives @@ -685,7 +817,9 @@ class BlivetMDRaidVolume(BlivetVolume): self._blivet.format_device(member_disk, label) # create new partition - member = self._blivet.new_partition(parents=[member_disk], grow=True) + member = self._blivet.new_partition( + parents=[member_disk], grow=True + ) self._blivet.create_device(member) self._blivet.format_device(member, fmt=get_format("mdmember")) members.append(member) @@ -697,16 +831,16 @@ class BlivetMDRaidVolume(BlivetVolume): def _update_from_device(self, param_name): """ Return True if param_name's value was retrieved from a looked-up device. """ - if param_name == 'raid_level': - self._volume['raid_level'] = self._device.level.name - elif param_name == 'raid_chunk_size': - self._volume['raid_chunk_size'] = str(self._device.chunk_size) - elif param_name == 'raid_device_count': - self._volume['raid_device_count'] = self._device.member_devices - elif param_name == 'raid_spare_count': - self._volume['raid_spare_count'] = self._device.spares - elif param_name == 'raid_metadata_version': - self._volume['raid_metadata_version'] = self._device.metadata_version + if param_name == "raid_level": + self._volume["raid_level"] = self._device.level.name + elif param_name == "raid_chunk_size": + self._volume["raid_chunk_size"] = str(self._device.chunk_size) + elif param_name == "raid_device_count": + self._volume["raid_device_count"] = self._device.member_devices + elif param_name == "raid_spare_count": + self._volume["raid_spare_count"] = self._device.spares + elif param_name == "raid_metadata_version": + self._volume["raid_metadata_version"] = self._device.metadata_version else: return super(BlivetMDRaidVolume, self)._update_from_device(param_name) @@ -728,7 +862,10 @@ class BlivetMDRaidVolume(BlivetVolume): try: do_partitioning(self._blivet) except Exception as e: - raise BlivetAnsibleError("failed to allocate partitions for mdraid '%s': %s" % (self._volume['name'], str(e))) + raise BlivetAnsibleError( + "failed to allocate partitions for mdraid '%s': %s" + % (self._volume["name"], str(e)) + ) raid_array = self._new_mdarray(members) @@ -764,16 +901,20 @@ _BLIVET_VOLUME_TYPES = { "disk": BlivetDiskVolume, "lvm": BlivetLVMVolume, "partition": BlivetPartitionVolume, - "raid": BlivetMDRaidVolume + "raid": BlivetMDRaidVolume, } def _get_blivet_volume(blivet_obj, volume, bpool=None): """ Return a BlivetVolume instance appropriate for the volume dict. """ global volume_defaults - volume_type = volume.get('type', bpool._pool['type'] if bpool else volume_defaults['type']) + volume_type = volume.get( + "type", bpool._pool["type"] if bpool else volume_defaults["type"] + ) if volume_type not in _BLIVET_VOLUME_TYPES: - raise BlivetAnsibleError("Volume '%s' has unknown type '%s'" % (volume['name'], volume_type)) + raise BlivetAnsibleError( + "Volume '%s' has unknown type '%s'" % (volume["name"], volume_type) + ) return _BLIVET_VOLUME_TYPES[volume_type](blivet_obj, volume, bpool=bpool) @@ -796,19 +937,19 @@ class BlivetPool(BlivetBase): if self.ultimately_present and self.__class__.blivet_device_class is not None: packages.extend(self.__class__.blivet_device_class._packages) - if self._pool.get('encryption'): - packages.extend(get_format('luks').packages) + if self._pool.get("encryption"): + packages.extend(get_format("luks").packages) return packages @property def ultimately_present(self): """ Should this pool be present when we are finished? """ - return self._pool.get('state', 'present') == 'present' + return self._pool.get("state", "present") == "present" @property def _is_raid(self): - return self._pool.get('raid_level') not in [None, "null", ""] + return self._pool.get("raid_level") not in [None, "null", ""] def _member_management_is_destructive(self): return False @@ -849,25 +990,30 @@ class BlivetPool(BlivetBase): if self._disks: return - if not self._device and not self._pool['disks']: - raise BlivetAnsibleError("no disks specified for pool '%s'" % self._pool['name']) - elif not isinstance(self._pool['disks'], list): + if not self._device and not self._pool["disks"]: + raise BlivetAnsibleError( + "no disks specified for pool '%s'" % self._pool["name"] + ) + elif not isinstance(self._pool["disks"], list): raise BlivetAnsibleError("pool disks must be specified as a list") disks = list() - for spec in self._pool['disks']: + for spec in self._pool["disks"]: device = self._blivet.devicetree.resolve_device(spec) if device is not None: # XXX fail if any disk isn't resolved? disks.append(device) - if self._pool['disks'] and not self._device and not disks: - raise BlivetAnsibleError("unable to resolve any disks specified for pool '%s' (%s)" % (self._pool['name'], self._pool['disks'])) + if self._pool["disks"] and not self._device and not disks: + raise BlivetAnsibleError( + "unable to resolve any disks specified for pool '%s' (%s)" + % (self._pool["name"], self._pool["disks"]) + ) self._disks = disks def _look_up_device(self): """ Look up the pool in blivet's device tree. """ - device = self._blivet.devicetree.resolve_device(self._pool['name']) + device = self._blivet.devicetree.resolve_device(self._pool["name"]) if device is None: return @@ -895,45 +1041,62 @@ class BlivetPool(BlivetBase): """ Return True if param_name's value was retrieved from a looked-up device. """ # We wouldn't have the pool device if the member devices weren't unlocked, so we do not # have to consider the case where the devices are unlocked like we do for volumes. - encrypted = bool(self._device.parents) and all("luks" in d.type for d in self._device.parents) - raid = len(self._device.parents) == 1 and hasattr(self._device.parents[0].raw_device, 'level') + encrypted = bool(self._device.parents) and all( + "luks" in d.type for d in self._device.parents + ) + raid = len(self._device.parents) == 1 and hasattr( + self._device.parents[0].raw_device, "level" + ) log.debug("BlivetPool._update_from_device: %s", self._device) - if param_name == 'disks': - self._pool['disks'] = [d.name for d in self._device.disks] - elif param_name == 'encryption': - self._pool['encryption'] = encrypted - elif param_name == 'encryption_key_size' and encrypted: - self._pool['encryption_key_size'] = self._device.parents[0].parents[0].format.key_size - elif param_name == 'encryption_key_file' and encrypted: - self._pool['encryption_key_file'] = self._device.parents[0].parents[0].format.key_file - elif param_name == 'encryption_cipher' and encrypted: - self._pool['encryption_cipher'] = self._device.parents[0].parents[0].format.cipher - elif param_name == 'encryption_luks_version' and encrypted: - self._pool['encryption_luks_version'] = self._device.parents[0].parents[0].format.luks_version - elif param_name == 'raid_level' and raid: - self._pool['raid_level'] = self._device.parents[0].raw_device.level.name - elif param_name == 'raid_chunk_size' and raid: - self._pool['raid_chunk_size'] = str(self._device.parents[0].raw_device.chunk_size) - elif param_name == 'raid_device_count' and raid: - self._pool['raid_device_count'] = self._device.parents[0].raw_device.member_devices - elif param_name == 'raid_spare_count' and raid: - self._pool['raid_spare_count'] = self._device.parents[0].raw_device.spares - elif param_name == 'raid_metadata_version' and raid: - self._pool['raid_metadata_version'] = self._device.parents[0].raw_device.metadata_version + if param_name == "disks": + self._pool["disks"] = [d.name for d in self._device.disks] + elif param_name == "encryption": + self._pool["encryption"] = encrypted + elif param_name == "encryption_key_size" and encrypted: + self._pool["encryption_key_size"] = ( + self._device.parents[0].parents[0].format.key_size + ) + elif param_name == "encryption_key_file" and encrypted: + self._pool["encryption_key_file"] = ( + self._device.parents[0].parents[0].format.key_file + ) + elif param_name == "encryption_cipher" and encrypted: + self._pool["encryption_cipher"] = ( + self._device.parents[0].parents[0].format.cipher + ) + elif param_name == "encryption_luks_version" and encrypted: + self._pool["encryption_luks_version"] = ( + self._device.parents[0].parents[0].format.luks_version + ) + elif param_name == "raid_level" and raid: + self._pool["raid_level"] = self._device.parents[0].raw_device.level.name + elif param_name == "raid_chunk_size" and raid: + self._pool["raid_chunk_size"] = str( + self._device.parents[0].raw_device.chunk_size + ) + elif param_name == "raid_device_count" and raid: + self._pool["raid_device_count"] = self._device.parents[ + 0 + ].raw_device.member_devices + elif param_name == "raid_spare_count" and raid: + self._pool["raid_spare_count"] = self._device.parents[0].raw_device.spares + elif param_name == "raid_metadata_version" and raid: + self._pool["raid_metadata_version"] = self._device.parents[ + 0 + ].raw_device.metadata_version else: return False return True - def _apply_defaults(self): global pool_defaults for name, default in pool_defaults.items(): if name in self._pool: continue - default = None if default in ('none', 'None', 'null') else default + default = None if default in ("none", "None", "null") else default if self._device: if not self._update_from_device(name): @@ -948,14 +1111,19 @@ class BlivetPool(BlivetBase): for disk in self._disks: if not disk.isleaf or disk.format.type is not None: if safe_mode: - raise BlivetAnsibleError("cannot remove existing formatting and/or devices on disk '%s' (pool '%s') in safe mode" % (disk.name, self._pool['name'])) + raise BlivetAnsibleError( + "cannot remove existing formatting and/or devices on disk '%s' (pool '%s') in safe mode" + % (disk.name, self._pool["name"]) + ) else: self._blivet.devicetree.recursive_remove(disk) if use_partitions: label = get_format("disklabel", device=disk.path) self._blivet.format_device(disk, label) - member = self._blivet.new_partition(parents=[disk], size=Size("256MiB"), grow=True) + member = self._blivet.new_partition( + parents=[disk], size=Size("256MiB"), grow=True + ) self._blivet.create_device(member) else: member = disk @@ -966,9 +1134,8 @@ class BlivetPool(BlivetBase): self._blivet.format_device(member, self._get_format()) members.append(member) - if self._is_raid: - raid_name = "%s-1" % self._pool['name'] + raid_name = "%s-1" % self._pool["name"] raid_array = self._new_mdarray(members, raid_name=raid_name) @@ -981,14 +1148,15 @@ class BlivetPool(BlivetBase): try: do_partitioning(self._blivet) except Exception: - raise BlivetAnsibleError("failed to allocate partitions for pool '%s'" % self._pool['name']) + raise BlivetAnsibleError( + "failed to allocate partitions for pool '%s'" % self._pool["name"] + ) return result - def _get_volumes(self): """ Set up BlivetVolume instances for this pool's volumes. """ - for volume in self._pool.get('volumes', []): + for volume in self._pool.get("volumes", []): bvolume = _get_blivet_volume(self._blivet, volume, self) self._blivet_volumes.append(bvolume) @@ -1013,7 +1181,10 @@ class BlivetPool(BlivetBase): return elif self._member_management_is_destructive(): if safe_mode: - raise BlivetAnsibleError("cannot remove and recreate existing pool '%s' in safe mode" % self._pool['name']) + raise BlivetAnsibleError( + "cannot remove and recreate existing pool '%s' in safe mode" + % self._pool["name"] + ) else: self._destroy() @@ -1031,15 +1202,22 @@ class BlivetPartitionPool(BlivetPool): self._device = self._disks[0] def _create(self): - if self._device.format.type != "disklabel" or \ - (disklabel_type and self._device.format.label_type != disklabel_type): + if self._device.format.type != "disklabel" or ( + disklabel_type and self._device.format.label_type != disklabel_type + ): if safe_mode: - raise BlivetAnsibleError("cannot remove existing formatting and/or devices on disk '%s' " - "(pool '%s') in safe mode" % (self._device.name, self._pool['name'])) + raise BlivetAnsibleError( + "cannot remove existing formatting and/or devices on disk '%s' " + "(pool '%s') in safe mode" % (self._device.name, self._pool["name"]) + ) else: - self._blivet.devicetree.recursive_remove(self._device, remove_device=False) + self._blivet.devicetree.recursive_remove( + self._device, remove_device=False + ) - label = get_format("disklabel", device=self._device.path, label_type=disklabel_type) + label = get_format( + "disklabel", device=self._device.path, label_type=disklabel_type + ) self._blivet.format_device(self._device, label) @@ -1053,9 +1231,13 @@ class BlivetLVMPool(BlivetPool): if self._device is None: return False - if self._pool['encryption'] and not all(m.encrypted for m in self._device.parents): + if self._pool["encryption"] and not all( + m.encrypted for m in self._device.parents + ): return True - elif not self._pool['encryption'] and any(m.encrypted for m in self._device.parents): + elif not self._pool["encryption"] and any( + m.encrypted for m in self._device.parents + ): return True return False @@ -1080,49 +1262,50 @@ class BlivetLVMPool(BlivetPool): members = self._manage_encryption(self._create_members()) try: - pool_device = self._blivet.new_vg(name=self._pool['name'], parents=members) + pool_device = self._blivet.new_vg(name=self._pool["name"], parents=members) except Exception as e: - raise BlivetAnsibleError("failed to set up pool '%s': %s" % (self._pool['name'], str(e))) + raise BlivetAnsibleError( + "failed to set up pool '%s': %s" % (self._pool["name"], str(e)) + ) self._blivet.create_device(pool_device) self._device = pool_device -_BLIVET_POOL_TYPES = { - "partition": BlivetPartitionPool, - "lvm": BlivetLVMPool -} +_BLIVET_POOL_TYPES = {"partition": BlivetPartitionPool, "lvm": BlivetLVMPool} def _get_blivet_pool(blivet_obj, pool): """ Return an appropriate BlivetPool instance for the pool dict. """ - if 'type' not in pool: + if "type" not in pool: global pool_defaults - pool['type'] = pool_defaults['type'] + pool["type"] = pool_defaults["type"] - if pool['type'] not in _BLIVET_POOL_TYPES: - raise BlivetAnsibleError("Pool '%s' has unknown type '%s'" % (pool['name'], pool['type'])) + if pool["type"] not in _BLIVET_POOL_TYPES: + raise BlivetAnsibleError( + "Pool '%s' has unknown type '%s'" % (pool["name"], pool["type"]) + ) - return _BLIVET_POOL_TYPES[pool['type']](blivet_obj, pool) + return _BLIVET_POOL_TYPES[pool["type"]](blivet_obj, pool) def manage_volume(b, volume): """ Schedule actions as needed to manage a single standalone volume. """ bvolume = _get_blivet_volume(b, volume) bvolume.manage() - volume['_device'] = bvolume._volume.get('_device', '') - volume['_raw_device'] = bvolume._volume.get('_raw_device', '') - volume['_mount_id'] = bvolume._volume.get('_mount_id', '') + volume["_device"] = bvolume._volume.get("_device", "") + volume["_raw_device"] = bvolume._volume.get("_raw_device", "") + volume["_mount_id"] = bvolume._volume.get("_mount_id", "") def manage_pool(b, pool): """ Schedule actions as needed to manage a single pool and its volumes. """ bpool = _get_blivet_pool(b, pool) bpool.manage() - for (volume, bvolume) in zip(pool['volumes'], bpool._blivet_volumes): - volume['_device'] = bvolume._volume.get('_device', '') - volume['_raw_device'] = bvolume._volume.get('_raw_device', '') - volume['_mount_id'] = bvolume._volume.get('_mount_id', '') + for (volume, bvolume) in zip(pool["volumes"], bpool._blivet_volumes): + volume["_device"] = bvolume._volume.get("_device", "") + volume["_raw_device"] = bvolume._volume.get("_raw_device", "") + volume["_mount_id"] = bvolume._volume.get("_mount_id", "") class FSTab(object): @@ -1141,7 +1324,7 @@ class FSTab(object): if self._entries: self.reset() - for line in open('/etc/fstab').readlines(): + for line in open("/etc/fstab").readlines(): if line.lstrip().startswith("#"): continue @@ -1150,23 +1333,27 @@ class FSTab(object): continue device = self._blivet.devicetree.resolve_device(fields[0]) - self._entries.append(dict(device_id=fields[0], - device_path=getattr(device, 'path', None), - fs_type=fields[2], - mount_point=fields[1], - mount_options=fields[3])) + self._entries.append( + dict( + device_id=fields[0], + device_path=getattr(device, "path", None), + fs_type=fields[2], + mount_point=fields[1], + mount_options=fields[3], + ) + ) def get_mount_info(pools, volumes, actions, fstab): - """ Return a list of argument dicts to pass to the mount module to manage mounts. + """Return a list of argument dicts to pass to the mount module to manage mounts. - The overall approach is to remove existing mounts associated with file systems - we are removing and those with changed mount points, re-adding them with the - new mount point later. + The overall approach is to remove existing mounts associated with file systems + we are removing and those with changed mount points, re-adding them with the + new mount point later. - Removed mounts go directly into the mount_info list, which is the return value, - while added/active mounts to a list that gets appended to the mount_info list - at the end to ensure that removals happen first. + Removed mounts go directly into the mount_info list, which is the return value, + while added/active mounts to a list that gets appended to the mount_info list + at the end to ensure that removals happen first. """ mount_info = list() mount_vols = list() @@ -1174,33 +1361,50 @@ def get_mount_info(pools, volumes, actions, fstab): # account for mounts removed by removing or reformatting volumes if actions: for action in actions: - if action.is_destroy and action.is_format and action.format.type is not None: - mount = fstab.lookup('device_path', action.device.path) + if ( + action.is_destroy + and action.is_format + and action.format.type is not None + ): + mount = fstab.lookup("device_path", action.device.path) if mount is not None: - mount_info.append({"src": mount['device_id'], "path": mount['mount_point'], - 'state': 'absent', 'fstype': mount['fs_type']}) + mount_info.append( + { + "src": mount["device_id"], + "path": mount["mount_point"], + "state": "absent", + "fstype": mount["fs_type"], + } + ) def handle_new_mount(volume, fstab): replace = None mounted = False - mount = fstab.lookup('device_path', volume['_device']) - if (volume['mount_point'] and volume['mount_point'].startswith('/')) \ - or volume['fs_type'] == 'swap': + mount = fstab.lookup("device_path", volume["_device"]) + if (volume["mount_point"] and volume["mount_point"].startswith("/")) or volume[ + "fs_type" + ] == "swap": mounted = True # handle removal of existing mounts of this volume - if mount and mount['fs_type'] != 'swap' and mount['mount_point'] != volume['mount_point']: - replace = dict(path=mount['mount_point'], state="absent") - elif mount and mount['fs_type'] == 'swap': - replace = dict(src=mount['device_id'], fstype="swap", path="none", state="absent") + if ( + mount + and mount["fs_type"] != "swap" + and mount["mount_point"] != volume["mount_point"] + ): + replace = dict(path=mount["mount_point"], state="absent") + elif mount and mount["fs_type"] == "swap": + replace = dict( + src=mount["device_id"], fstype="swap", path="none", state="absent" + ) return mounted, replace # account for mounts that we set up or are replacing in pools for pool in pools: - for volume in pool['volumes']: - if pool['state'] == 'present' and volume['state'] == 'present': + for volume in pool["volumes"]: + if pool["state"] == "present" and volume["state"] == "present": mounted, replace = handle_new_mount(volume, fstab) if replace: mount_info.append(replace) @@ -1209,7 +1413,7 @@ def get_mount_info(pools, volumes, actions, fstab): # account for mounts that we set up or are replacing in standalone volumes for volume in volumes: - if volume['state'] == 'present': + if volume["state"] == "present": mounted, replace = handle_new_mount(volume, fstab) if replace: mount_info.append(replace) @@ -1217,13 +1421,19 @@ def get_mount_info(pools, volumes, actions, fstab): mount_vols.append(volume) for volume in mount_vols: - mount_info.append({'src': volume['_mount_id'], - 'path': volume['mount_point'] if volume['fs_type'] != "swap" else "none", - 'fstype': volume['fs_type'], - 'opts': volume['mount_options'], - 'dump': volume['mount_check'], - 'passno': volume['mount_passno'], - 'state': 'mounted' if volume['fs_type'] != "swap" else "present"}) + mount_info.append( + { + "src": volume["_mount_id"], + "path": volume["mount_point"] + if volume["fs_type"] != "swap" + else "none", + "fstype": volume["fs_type"], + "opts": volume["mount_options"], + "dump": volume["mount_check"], + "passno": volume["mount_passno"], + "state": "mounted" if volume["fs_type"] != "swap" else "present", + } + ) return mount_info @@ -1231,15 +1441,19 @@ def get_mount_info(pools, volumes, actions, fstab): def get_crypt_info(actions): info = list() for action in actions: - if not (action.is_format and action.format.type == 'luks'): + if not (action.is_format and action.format.type == "luks"): continue - info.append(dict(backing_device=action.device.path, - name=action.format.map_name, - password=action.format.key_file or '-', - state='present' if action.is_create else 'absent')) + info.append( + dict( + backing_device=action.device.path, + name=action.format.map_name, + password=action.format.key_file or "-", + state="present" if action.is_create else "absent", + ) + ) - return sorted(info, key=lambda e: e['state']) + return sorted(info, key=lambda e: e["state"]) def get_required_packages(b, pools, volumes): @@ -1259,66 +1473,70 @@ def get_required_packages(b, pools, volumes): def update_fstab_identifiers(b, pools, volumes): - """ Update fstab device identifiers. + """Update fstab device identifiers. - This is to pick up new UUIDs for newly-formatted devices. + This is to pick up new UUIDs for newly-formatted devices. """ all_volumes = volumes[:] for pool in pools: - if not pool['state'] == 'present': + if not pool["state"] == "present": continue - all_volumes += pool['volumes'] + all_volumes += pool["volumes"] for volume in all_volumes: - if volume['state'] == 'present': - device = b.devicetree.resolve_device(volume['_mount_id']) - if device is None and volume['encryption']: - device = b.devicetree.resolve_device(volume['_raw_device']) + if volume["state"] == "present": + device = b.devicetree.resolve_device(volume["_mount_id"]) + if device is None and volume["encryption"]: + device = b.devicetree.resolve_device(volume["_raw_device"]) if device is not None and not device.isleaf: device = device.children[0] - volume['_device'] = device.path + volume["_device"] = device.path if device is None: - raise BlivetAnsibleError("failed to look up device for volume %s (%s/%s)" % (volume['name'], volume['_device'], volume['_mount_id'])) - volume['_mount_id'] = device.fstab_spec - if device.format.type == 'swap': + raise BlivetAnsibleError( + "failed to look up device for volume %s (%s/%s)" + % (volume["name"], volume["_device"], volume["_mount_id"]) + ) + volume["_mount_id"] = device.fstab_spec + if device.format.type == "swap": device.format.setup() if device.status: - volume['_kernel_device'] = os.path.realpath(device.path) + volume["_kernel_device"] = os.path.realpath(device.path) if device.raw_device.status: - volume['_raw_kernel_device'] = os.path.realpath(device.raw_device.path) + volume["_raw_kernel_device"] = os.path.realpath(device.raw_device.path) def activate_swaps(b, pools, volumes): """ Activate all swaps specified as present. """ all_volumes = volumes[:] for pool in pools: - if not pool['state'] == 'present': + if not pool["state"] == "present": continue - all_volumes += pool['volumes'] + all_volumes += pool["volumes"] for volume in all_volumes: - if volume['state'] == 'present': - device = b.devicetree.resolve_device(volume['_mount_id']) - if device.format.type == 'swap': + if volume["state"] == "present": + device = b.devicetree.resolve_device(volume["_mount_id"]) + if device.format.type == "swap": device.format.setup() def run_module(): # available arguments/parameters that a user can pass module_args = dict( - pools=dict(type='list'), - volumes=dict(type='list'), - packages_only=dict(type='bool', required=False, default=False), - disklabel_type=dict(type='str', required=False, default=None), - safe_mode=dict(type='bool', required=False, default=True), - pool_defaults=dict(type='dict', required=False), - volume_defaults=dict(type='dict', required=False), - use_partitions=dict(type='bool', required=False, default=True), - diskvolume_mkfs_option_map=dict(type='dict', required=False, default={})) + pools=dict(type="list"), + volumes=dict(type="list"), + packages_only=dict(type="bool", required=False, default=False), + disklabel_type=dict(type="str", required=False, default=None), + safe_mode=dict(type="bool", required=False, default=True), + pool_defaults=dict(type="dict", required=False), + volume_defaults=dict(type="dict", required=False), + use_partitions=dict(type="bool", required=False, default=True), + diskvolume_mkfs_option_map=dict(type="dict", required=False, default={}), + ) # seed the result dict in the object result = dict( @@ -1332,47 +1550,52 @@ def run_module(): packages=list(), ) - module = AnsibleModule(argument_spec=module_args, - supports_check_mode=True) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) if not BLIVET_PACKAGE: - module.fail_json(msg="Failed to import the blivet or blivet3 Python modules", - exception=inspect.cleandoc(""" + module.fail_json( + msg="Failed to import the blivet or blivet3 Python modules", + exception=inspect.cleandoc( + """ blivet3 exception: {} blivet exception: - {}""").format(LIB_IMP_ERR3, LIB_IMP_ERR)) + {}""" + ).format(LIB_IMP_ERR3, LIB_IMP_ERR), + ) - if not module.params['pools'] and not module.params['volumes']: + if not module.params["pools"] and not module.params["volumes"]: module.exit_json(**result) global disklabel_type - disklabel_type = module.params['disklabel_type'] + disklabel_type = module.params["disklabel_type"] global use_partitions - use_partitions = module.params['use_partitions'] + use_partitions = module.params["use_partitions"] global safe_mode - safe_mode = module.params['safe_mode'] + safe_mode = module.params["safe_mode"] global diskvolume_mkfs_option_map - diskvolume_mkfs_option_map = module.params['diskvolume_mkfs_option_map'] + diskvolume_mkfs_option_map = module.params["diskvolume_mkfs_option_map"] global pool_defaults - if 'pool_defaults' in module.params: - pool_defaults = module.params['pool_defaults'] + if "pool_defaults" in module.params: + pool_defaults = module.params["pool_defaults"] global volume_defaults - if 'volume_defaults' in module.params: - volume_defaults = module.params['volume_defaults'] + if "volume_defaults" in module.params: + volume_defaults = module.params["volume_defaults"] b = Blivet() b.reset() fstab = FSTab(b) actions = list() - if module.params['packages_only']: + if module.params["packages_only"]: try: - result['packages'] = get_required_packages(b, module.params['pools'], module.params['volumes']) + result["packages"] = get_required_packages( + b, module.params["pools"], module.params["volumes"] + ) except BlivetAnsibleError as e: module.fail_json(msg=str(e), **result) module.exit_json(**result) @@ -1388,44 +1611,56 @@ def run_module(): sys_path = action.device.path if os.path.islink(sys_path): sys_path = os.readlink(action.device.path) - trigger(action='change', subsystem='block', name=os.path.basename(sys_path)) + trigger(action="change", subsystem="block", name=os.path.basename(sys_path)) def action_dict(action): - return dict(action=action.type_desc_str, - fs_type=action.format.type if action.is_format else None, - device=action.device.path) + return dict( + action=action.type_desc_str, + fs_type=action.format.type if action.is_format else None, + device=action.device.path, + ) - duplicates = find_duplicate_names(module.params['pools']) + duplicates = find_duplicate_names(module.params["pools"]) if duplicates: - module.fail_json(msg="multiple pools with the same name: {0}".format(",".join(duplicates)), - **result) - for pool in module.params['pools']: - duplicates = find_duplicate_names(pool.get('volumes', list())) + module.fail_json( + msg="multiple pools with the same name: {0}".format(",".join(duplicates)), + **result + ) + for pool in module.params["pools"]: + duplicates = find_duplicate_names(pool.get("volumes", list())) if duplicates: - module.fail_json(msg="multiple volumes in pool '{0}' with the " - "same name: {1}".format(pool['name'], ",".join(duplicates)), - **result) + module.fail_json( + msg="multiple volumes in pool '{0}' with the " + "same name: {1}".format(pool["name"], ",".join(duplicates)), + **result + ) try: manage_pool(b, pool) except BlivetAnsibleError as e: module.fail_json(msg=str(e), **result) - duplicates = find_duplicate_names(module.params['volumes']) + duplicates = find_duplicate_names(module.params["volumes"]) if duplicates: - module.fail_json(msg="multiple volumes with the same name: {0}".format(",".join(duplicates)), - **result) - for volume in module.params['volumes']: + module.fail_json( + msg="multiple volumes with the same name: {0}".format(",".join(duplicates)), + **result + ) + for volume in module.params["volumes"]: try: manage_volume(b, volume) except BlivetAnsibleError as e: module.fail_json(msg=str(e), **result) scheduled = b.devicetree.actions.find() - result['packages'] = b.packages[:] + result["packages"] = b.packages[:] for action in scheduled: - if (action.is_destroy or action.is_resize) and action.is_format and action.format.exists and \ - (action.format.mountable or action.format.type == "swap"): + if ( + (action.is_destroy or action.is_resize) + and action.is_format + and action.format.exists + and (action.format.mountable or action.format.type == "swap") + ): action.format.teardown() if scheduled: @@ -1433,21 +1668,27 @@ def run_module(): callbacks.action_executed.add(record_action) callbacks.action_executed.add(ensure_udev_update) try: - b.devicetree.actions.process(devices=b.devicetree.devices, dry_run=module.check_mode) + b.devicetree.actions.process( + devices=b.devicetree.devices, dry_run=module.check_mode + ) except Exception as e: - module.fail_json(msg="Failed to commit changes to disk: %s" % str(e), **result) + module.fail_json( + msg="Failed to commit changes to disk: %s" % str(e), **result + ) finally: - result['changed'] = True - result['actions'] = [action_dict(a) for a in actions] + result["changed"] = True + result["actions"] = [action_dict(a) for a in actions] - update_fstab_identifiers(b, module.params['pools'], module.params['volumes']) - activate_swaps(b, module.params['pools'], module.params['volumes']) + update_fstab_identifiers(b, module.params["pools"], module.params["volumes"]) + activate_swaps(b, module.params["pools"], module.params["volumes"]) - result['mounts'] = get_mount_info(module.params['pools'], module.params['volumes'], actions, fstab) - result['crypts'] = get_crypt_info(actions) - result['leaves'] = [d.path for d in b.devicetree.leaves] - result['pools'] = module.params['pools'] - result['volumes'] = module.params['volumes'] + result["mounts"] = get_mount_info( + module.params["pools"], module.params["volumes"], actions, fstab + ) + result["crypts"] = get_crypt_info(actions) + result["leaves"] = [d.path for d in b.devicetree.leaves] + result["pools"] = module.params["pools"] + result["volumes"] = module.params["volumes"] # success - return result module.exit_json(**result) @@ -1456,5 +1697,6 @@ def run_module(): def main(): run_module() -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/library/blockdev_info.py b/library/blockdev_info.py index 52ddd78..ca1577f 100644 --- a/library/blockdev_info.py +++ b/library/blockdev_info.py @@ -1,35 +1,41 @@ #!/usr/bin/python +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", } -DOCUMENTATION = ''' +DOCUMENTATION = """ --- module: blockdev_info short_description: Collect info about block devices in the system. version_added: "2.5" description: + - "WARNING: Do not use this module directly! It is only for role internal use." - "This module collects information about block devices" -options: +options: {} author: - - David Lehman (dlehman@redhat.com) -''' + - David Lehman (@dwlehman) +""" -EXAMPLES = ''' +EXAMPLES = """ - name: Get info about block devices blockdev_info: register: blk_info -''' +""" -RETURN = ''' +RETURN = """ info: description: dict w/ device path keys and device info dict values + returned: success type: dict -''' +""" import os import shlex @@ -38,7 +44,7 @@ from ansible.module_utils.basic import AnsibleModule LSBLK_DEVICE_TYPES = {"part": "partition"} -DEV_MD_DIR = '/dev/md' +DEV_MD_DIR = "/dev/md" def fixup_md_path(path): @@ -59,7 +65,9 @@ def fixup_md_path(path): def get_block_info(run_cmd): - buf = run_cmd(["lsblk", "-o", "NAME,FSTYPE,LABEL,UUID,TYPE,SIZE", "-p", "-P", "-a"])[1] + buf = run_cmd( + ["lsblk", "-o", "NAME,FSTYPE,LABEL,UUID,TYPE,SIZE", "-p", "-P", "-a"] + )[1] info = dict() for line in buf.splitlines(): dev = dict() @@ -75,7 +83,7 @@ def get_block_info(run_cmd): dev[key.lower()] = LSBLK_DEVICE_TYPES.get(value, value) if dev: - info[dev['name']] = dev + info[dev["name"]] = dev return info @@ -87,13 +95,10 @@ def run_module(): info=None, ) - module = AnsibleModule( - argument_spec=module_args, - supports_check_mode=True - ) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) try: - result['info'] = get_block_info(module.run_command) + result["info"] = get_block_info(module.run_command) except Exception: module.fail_json(msg="Failed to collect block device info.") @@ -104,5 +109,5 @@ def main(): run_module() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/library/bsize.py b/library/bsize.py index 40442f5..524b0f9 100644 --- a/library/bsize.py +++ b/library/bsize.py @@ -1,12 +1,16 @@ #!/usr/bin/python +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", } -DOCUMENTATION = ''' +DOCUMENTATION = """ --- module: bsize @@ -15,6 +19,7 @@ short_description: Module for basic manipulation with byte sizes version_added: "2.5" description: + - "WARNING: Do not use this module directly! It is only for role internal use." - "Module accepts byte size strings with the units and produces strings in form of input accepted by different storage tools" @@ -23,67 +28,72 @@ options: description: - String containing number and byte units required: true + type: str author: - - Jan Pokorny (japokorn@redhat.com) -''' + - Jan Pokorny (@japokorn) +""" -EXAMPLES = ''' +EXAMPLES = """ # Obtain sizes in format for various tools - name: Get 10 KiB size bsize: size: 10 KiB -''' +""" -RETURN = ''' +RETURN = """ size: description: Size in binary format units type: str + returned: success bytes: description: Size in bytes type: int + returned: success lvm: description: Size in binary format. No space after the number, first letter of unit prefix in lowercase only type: str + returned: success parted: description: Size in binary format. No space after the number type: str -''' + returned: success +""" from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.storage_lsr.size import Size + def run_module(): # available arguments/parameters that a user can pass module_args = dict( - size=dict(type='str', required=True), + size=dict(type="str", required=True), ) # seed the result dict in the object - result = dict( - changed=False - ) + result = dict(changed=False) - module = AnsibleModule(argument_spec=module_args, - supports_check_mode=True) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) - size = Size(module.params['size']) + size = Size(module.params["size"]) - result['size'] = size.get(fmt="%d %sb") - result['bytes'] = size.bytes - result['lvm'] = size.get(fmt="%d%sb").lower()[:-2] - result['parted'] = size.get(fmt="%d%sb") + result["size"] = size.get(fmt="%d %sb") + result["bytes"] = size.bytes + result["lvm"] = size.get(fmt="%d%sb").lower()[:-2] + result["parted"] = size.get(fmt="%d%sb") # use whatever logic you need to determine whether or not this module # made any modifications to your target - result['changed'] = False + result["changed"] = False # success - return result module.exit_json(**result) + def main(): run_module() -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/library/find_unused_disk.py b/library/find_unused_disk.py index 0a6fc7d..c688170 100644 --- a/library/find_unused_disk.py +++ b/library/find_unused_disk.py @@ -1,10 +1,15 @@ #!/usr/bin/python -DOCUMENTATION = ''' +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = """ --- module: find_unused_disk short_description: Gets unused disks description: + - "WARNING: Do not use this module directly! It is only for role internal use." - Disks are considered in ascending alphanumeric sorted order. - Disks that meet all conditions are considered 'empty' and returned (using kernel device name) in a list. - 1. No known signatures exist on the disk, with the exception of partition tables. @@ -15,18 +20,18 @@ description: - Number of returned disks defaults to first 10, but can be specified with 'max_return' argument. author: Eda Zhou (@edamamez) options: - option-name: max_return - description: Sets the maximum number of unused disks to return. - default: 10 - type: int - - option-name: min_size - description: Specifies the minimum disk size to return an unused disk. - default: 0 - type: str -''' - -EXAMPLES = ''' + max_return: + description: Sets the maximum number of unused disks to return. + default: 10 + type: int + + min_size: + description: Specifies the minimum disk size to return an unused disk. + default: 0 + type: str +""" + +EXAMPLES = """ - name: test finding first unused device module hosts: localhost tasks: @@ -38,9 +43,9 @@ EXAMPLES = ''' - name: dump test output debug: msg: '{{ testout }}' -''' +""" -RETURN = ''' +RETURN = """ disk_name: description: Information about unused disks returned: On success @@ -50,14 +55,15 @@ disk_name: description: Unused disk(s) that have been found returned: On success type: list - samples: ["sda1", "dm-0", "dm-3"] - ["sda"] + samples: | + ["sda1", "dm-0", "dm-3"] + ["sda"] none: description: No unused disks were found returned: On success type: string sample: "Unable to find unused disk" -''' +""" import os @@ -68,7 +74,7 @@ from ansible.module_utils.storage_lsr.size import Size SYS_CLASS_BLOCK = "/sys/class/block/" -IGNORED_DEVICES = [re.compile(r'^/dev/nullb\d+$')] +IGNORED_DEVICES = [re.compile(r"^/dev/nullb\d+$")] def is_ignored(disk_path): @@ -78,13 +84,13 @@ def is_ignored(disk_path): def no_signature(run_command, disk_path): """Return true if no known signatures exist on the disk.""" - signatures = run_command(['blkid', '-p', disk_path]) - return not 'UUID' in signatures[1] + signatures = run_command(["blkid", "-p", disk_path]) + return "UUID" not in signatures[1] def no_holders(disk_path): """Return true if the disk has no holders.""" - holders = os.listdir(SYS_CLASS_BLOCK + get_sys_name(disk_path) + '/holders/') + holders = os.listdir(SYS_CLASS_BLOCK + get_sys_name(disk_path) + "/holders/") return len(holders) == 0 @@ -101,36 +107,45 @@ def get_sys_name(disk_path): if not os.path.islink(disk_path): return os.path.basename(disk_path) - node_dir = '/'.join(disk_path.split('/')[-1]) - return os.path.normpath(node_dir + '/' + os.readlink(disk_path)) + node_dir = "/".join(disk_path.split("/")[-1]) + return os.path.normpath(node_dir + "/" + os.readlink(disk_path)) def get_partitions(disk_path): sys_name = get_sys_name(disk_path) partitions = list() for filename in os.listdir(SYS_CLASS_BLOCK + sys_name): - if re.match(sys_name + r'p?\d+$', filename): + if re.match(sys_name + r"p?\d+$", filename): partitions.append(filename) return partitions def get_disks(run_command): - buf = run_command(["lsblk", "-p", "--pairs", "--bytes", "-o", "NAME,TYPE,SIZE,FSTYPE"])[1] + buf = run_command( + ["lsblk", "-p", "--pairs", "--bytes", "-o", "NAME,TYPE,SIZE,FSTYPE"] + )[1] disks = dict() for line in buf.splitlines(): if not line: continue - m = re.search(r'NAME="(?P[^"]*)" TYPE="(?P[^"]*)" SIZE="(?P\d+)" FSTYPE="(?P[^"]*)"', line) + m = re.search( + r'NAME="(?P[^"]*)" TYPE="(?P[^"]*)" SIZE="(?P\d+)" FSTYPE="(?P[^"]*)"', + line, + ) if m is None: print(line) continue - if m.group('type') != "disk": + if m.group("type") != "disk": continue - disks[m.group('path')] = {"type": m.group('type'), "size": m.group('size'), "fstype": m.group('fstype')} + disks[m.group("path")] = { + "type": m.group("type"), + "size": m.group("size"), + "fstype": m.group("fstype"), + } return disks @@ -138,19 +153,13 @@ def get_disks(run_command): def run_module(): """Create the module""" module_args = dict( - max_return=dict(type='int', required=False, default=10), - min_size=dict(type='str', required=False, default=0) + max_return=dict(type="int", required=False, default=10), + min_size=dict(type="str", required=False, default=0), ) - result = dict( - changed=False, - disks=[] - ) + result = dict(changed=False, disks=[]) - module = AnsibleModule( - argument_spec=module_args, - supports_check_mode=True - ) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) run_command = module.run_command @@ -161,7 +170,7 @@ def run_module(): if attrs["fstype"]: continue - if Size(attrs["size"]).bytes < Size(module.params['min_size']).bytes: + if Size(attrs["size"]).bytes < Size(module.params["min_size"]).bytes: continue if get_partitions(path): @@ -173,14 +182,14 @@ def run_module(): if not can_open(path): continue - result['disks'].append(os.path.basename(path)) - if len(result['disks']) >= module.params['max_return']: + result["disks"].append(os.path.basename(path)) + if len(result["disks"]) >= module.params["max_return"]: break - if not result['disks']: - result['disks'] = "Unable to find unused disk" + if not result["disks"]: + result["disks"] = "Unable to find unused disk" else: - result['disks'].sort() + result["disks"].sort() module.exit_json(**result) @@ -190,5 +199,5 @@ def main(): run_module() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/library/lvm_gensym.py b/library/lvm_gensym.py index 49d1822..3e0f613 100644 --- a/library/lvm_gensym.py +++ b/library/lvm_gensym.py @@ -1,66 +1,75 @@ #!/usr/bin/python """Generates unique, default names for a volume group and logical volume""" -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils import facts +from __future__ import absolute_import, division, print_function + +__metaclass__ = type ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", } -DOCUMENTATION = ''' +DOCUMENTATION = """ --- module: lvm_gensym short_description: Generate default names for lvm variables version_added: "2.4" -description: - - "Module accepts two input strings consisting of a file system type and +description: + - "WARNING: Do not use this module directly! It is only for role internal use." + - "Module accepts two input strings consisting of a file system type and a mount point path, and outputs names based on system information" options: fs_type: description: - - String describing the desired file system type - required: true + - String describing the desired file system type + required: true + type: str mount: description: - - String describing the mount point path + - String describing the mount point path required: true -author: - - Tim Flannagan (tflannag@redhat.com) -''' + type: str +author: + - Tim Flannagan (@timflannagan) +""" -EXAMPLES = ''' -- name: Generate names +EXAMPLES = """ +- name: Generate names lvm_gensym: fs_type: "{{ fs_type }}" mount: "{{ mount_point }}" register: lvm_results when: lvm_vg == "" and mount_point != "" and fs_type != "" -''' +""" -RETURN = ''' +RETURN = """ vg_name: description: The default generated name for an unspecified volume group type: str - + returned: success lv_name: description: The default generated name for an unspecified logical volume type: str -''' + returned: success +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils import facts def get_os_name(): """Search the host file and return the name in the ID column""" - for line in open('/etc/os-release').readlines(): - if not line.find('ID='): + for line in open("/etc/os-release").readlines(): + if not line.find("ID="): os_name = line[3:] break - os_name = os_name.replace('\n', '').replace('"', '') + os_name = os_name.replace("\n", "").replace('"', "") return os_name + def name_is_unique(name, used_names): """Check if name is contained in the used_names list and return boolean value""" if name not in used_names: @@ -68,14 +77,15 @@ def name_is_unique(name, used_names): return False + def get_unique_name_from_base(base_name, used_names): """Generate a unique name given a base name and a list of used names, and return that unique name""" counter = 0 while not name_is_unique(base_name, used_names): if counter == 0: - base_name = base_name + '_' + str(counter) + base_name = base_name + "_" + str(counter) else: - base_name = base_name[:-2] + '_' + str(counter) + base_name = base_name[:-2] + "_" + str(counter) counter += 1 return base_name @@ -83,8 +93,8 @@ def get_unique_name_from_base(base_name, used_names): def get_vg_name_base(host_name, os_name): """Return a base name for a volume group based on the host and os names""" - if host_name != None and len(host_name) != 0: - vg_default = os_name + '_' + host_name + if host_name is not None and len(host_name) != 0: + vg_default = os_name + "_" + host_name else: vg_default = os_name @@ -93,65 +103,68 @@ def get_vg_name_base(host_name, os_name): def get_vg_name(host_name, lvm_facts): """Generate a base volume group name, verify its uniqueness, and return that unique name""" - used_vg_names = lvm_facts['vgs'].keys() + used_vg_names = lvm_facts["vgs"].keys() os_name = get_os_name() name = get_vg_name_base(host_name, os_name) return get_unique_name_from_base(name, used_vg_names) + def get_lv_name_base(fs_type, mount_point): """Return a logical volume base name using given parameters""" - if 'swap' in fs_type.lower(): - lv_default = 'swap' - elif mount_point.startswith('/'): - if mount_point == '/': - lv_default = 'root' + if "swap" in fs_type.lower(): + lv_default = "swap" + elif mount_point.startswith("/"): + if mount_point == "/": + lv_default = "root" else: - lv_default = mount_point[1:].replace('/', '_') + lv_default = mount_point[1:].replace("/", "_") else: - lv_default = 'lv' + lv_default = "lv" return lv_default def get_lv_name(fs_type, mount_point, lvm_facts): """Return a unique logical volume name based on specified file system type, mount point, and system facts""" - used_lv_names = lvm_facts['lvs'].keys() + used_lv_names = lvm_facts["lvs"].keys() name = get_lv_name_base(fs_type, mount_point) return get_unique_name_from_base(name, used_lv_names) + def run_module(): """Setup and initialize all relevant ansible module data""" module_args = dict( - mount=dict(type='str', required=True), - fs_type=dict(type='str', required=True) + mount=dict(type="str", required=True), fs_type=dict(type="str", required=True) ) - result = dict( - changed=False, - vg_name='', - lv_name='' - ) + result = dict(changed=False, vg_name="", lv_name="") - module = AnsibleModule( - argument_spec=module_args, - supports_check_mode=True - ) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) - lvm_facts = facts.ansible_facts(module)['lvm'] - host_name = facts.ansible_facts(module)['nodename'].lower().replace('.', '_').replace('-', '_') + lvm_facts = facts.ansible_facts(module)["lvm"] + host_name = ( + facts.ansible_facts(module)["nodename"] + .lower() + .replace(".", "_") + .replace("-", "_") + ) - result['lv_name'] = get_lv_name(module.params['fs_type'], module.params['mount'], lvm_facts) - result['vg_name'] = get_vg_name(host_name, lvm_facts) + result["lv_name"] = get_lv_name( + module.params["fs_type"], module.params["mount"], lvm_facts + ) + result["vg_name"] = get_vg_name(host_name, lvm_facts) - if result['lv_name'] != '' and result['vg_name'] != '': + if result["lv_name"] != "" and result["vg_name"] != "": module.exit_json(**result) else: module.fail_json(msg="Unable to initialize both group and volume names") + def main(): run_module() -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/library/resolve_blockdev.py b/library/resolve_blockdev.py index 007bb28..df9dcb1 100644 --- a/library/resolve_blockdev.py +++ b/library/resolve_blockdev.py @@ -1,17 +1,22 @@ #!/usr/bin/python +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community' + "metadata_version": "1.1", + "status": ["preview"], + "supported_by": "community", } -DOCUMENTATION = ''' +DOCUMENTATION = """ --- module: resolve_blockdev short_description: Resolve block device specification to device node path. version_added: "2.5" description: + - "WARNING: Do not use this module directly! It is only for role internal use." - "This module accepts various forms of block device identifiers and resolves them to the correct block device node path." options: @@ -19,11 +24,12 @@ options: description: - String describing a block device required: true + type: str author: - - David Lehman (dlehman@redhat.com) -''' + - David Lehman (@dwlehman) +""" -EXAMPLES = ''' +EXAMPLES = """ - name: Resolve device by label resolve_blockdev: spec: LABEL=MyData @@ -35,13 +41,14 @@ EXAMPLES = ''' - name: Resolve device by /dev/disk/by-id symlink name resolve_blockdev: spec: wwn-0x5000c5005bc37f3f -''' +""" -RETURN = ''' +RETURN = """ device: description: Path to block device node type: str -''' + returned: success +""" import glob import os @@ -52,37 +59,42 @@ from ansible.module_utils.basic import AnsibleModule DEV_MD = "/dev/md" DEV_MAPPER = "/dev/mapper" SYS_CLASS_BLOCK = "/sys/class/block" -SEARCH_DIRS = ['/dev', DEV_MAPPER, DEV_MD] + glob.glob("/dev/disk/by-*") -MD_KERNEL_DEV = re.compile(r'/dev/md\d+(p\d+)?$') +SEARCH_DIRS = ["/dev", DEV_MAPPER, DEV_MD] + glob.glob("/dev/disk/by-*") +MD_KERNEL_DEV = re.compile(r"/dev/md\d+(p\d+)?$") def resolve_blockdev(spec, run_cmd): if "=" in spec: device = run_cmd("blkid -t %s -o device" % spec)[1].strip() - elif not spec.startswith('/'): + elif not spec.startswith("/"): for devdir in SEARCH_DIRS: device = "%s/%s" % (devdir, spec) if os.path.exists(device): break else: - device = '' + device = "" else: device = spec if not device or not os.path.exists(device): - return '' + return "" return canonical_device(os.path.realpath(device)) def _get_dm_name_from_kernel_dev(kdev): - return open("%s/%s/dm/name" % (SYS_CLASS_BLOCK, os.path.basename(kdev))).read().strip() + return ( + open("%s/%s/dm/name" % (SYS_CLASS_BLOCK, os.path.basename(kdev))).read().strip() + ) def _get_md_name_from_kernel_dev(kdev): minor = os.minor(os.stat(kdev).st_rdev) - return next(name for name in os.listdir(DEV_MD) - if os.minor(os.stat("%s/%s" % (DEV_MD, name)).st_rdev) == minor) + return next( + name + for name in os.listdir(DEV_MD) + if os.minor(os.stat("%s/%s" % (DEV_MD, name)).st_rdev) == minor + ) def canonical_device(device): @@ -94,26 +106,27 @@ def canonical_device(device): def run_module(): - module_args = dict( - spec=dict(type='str') - ) + module_args = dict(spec=dict(type="str")) result = dict( device=None, ) - module = AnsibleModule( - argument_spec=module_args, - supports_check_mode=True - ) + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) try: - result['device'] = resolve_blockdev(module.params['spec'], run_cmd=module.run_command) + result["device"] = resolve_blockdev( + module.params["spec"], run_cmd=module.run_command + ) except Exception: pass - if not result['device'] or not os.path.exists(result['device']): - module.fail_json(msg="The {} device spec could not be resolved".format(module.params['spec'])) + if not result["device"] or not os.path.exists(result["device"]): + module.fail_json( + msg="The {0} device spec could not be resolved".format( + module.params["spec"] + ) + ) module.exit_json(**result) @@ -122,5 +135,5 @@ def main(): run_module() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/module_utils/storage_lsr/size.py b/module_utils/storage_lsr/size.py index 16f3d7c..1e91faa 100644 --- a/module_utils/storage_lsr/size.py +++ b/module_utils/storage_lsr/size.py @@ -1,4 +1,6 @@ -#!/bin/python2 +from __future__ import absolute_import, division, print_function + +__metaclass__ = type import re @@ -7,15 +9,20 @@ BINARY_FACTOR = 2 ** 10 # index of the item in the list determines the exponent for size computation # e.g. size_in_bytes = value * (DECIMAL_FACTOR ** (index(mega)+1)) = value * (1000 ** (1+1)) -PREFIXES_DECIMAL = [["k", "M", "G", "T", "P", "E", "Z", "Y"], - ["kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta"]] -PREFIXES_BINARY = [["Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"], - ["kibi", "mebi", "gibi", "tebi", "pebi", "exbi", "zebi", "yobi"]] +# pylint: disable=bad-whitespace +PREFIXES_DECIMAL = [ + ["k", "M", "G", "T", "P", "E", "Z", "Y"], # nopep8 + ["kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta"], +] # nopep8 +PREFIXES_BINARY = [ + ["Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"], # nopep8 + ["kibi", "mebi", "gibi", "tebi", "pebi", "exbi", "zebi", "yobi"], +] # nopep8 SUFFIXES = ["bytes", "byte", "B"] + class Size(object): - ''' Class for basic manipulation of the sizes in *bytes - ''' + """Class for basic manipulation of the sizes in *bytes""" def __init__(self, value): raw_number, raw_units = self._parse_input(str(value)) @@ -25,9 +32,9 @@ class Size(object): self.units = raw_units def _parse_input(self, value): - ''' splits input string into number and unit parts - returns number part, unit part - ''' + """splits input string into number and unit parts + returns number part, unit part + """ m = re.search("^(.*?)([^0-9]*)$", value) raw_number = m.group(1).strip() @@ -39,12 +46,12 @@ class Size(object): return raw_number, raw_units def _parse_units(self, raw_units): - ''' - gets string containing size units and - returns *_FACTOR (BINARY or DECIMAL) and the prefix position (not index!) - in the PREFIXES_* list - If no unit is specified defaults to BINARY and Bytes - ''' + """ + gets string containing size units and + returns *_FACTOR (BINARY or DECIMAL) and the prefix position (not index!) + in the PREFIXES_* list + If no unit is specified defaults to BINARY and Bytes + """ prefix = raw_units no_suffix_flag = True @@ -54,7 +61,7 @@ class Size(object): for suffix in SUFFIXES: if raw_units.lower().endswith(suffix.lower()): no_suffix_flag = False - prefix = raw_units[:-len(suffix)] + prefix = raw_units[: -len(suffix)] break if prefix == "": @@ -87,18 +94,18 @@ class Size(object): if idx < 0 or not valid_suffix: raise ValueError("Unable to identify unit '%s'" % raw_units) - return used_factor, idx+1 + return used_factor, idx + 1 def _parse_number(self, raw_number): - ''' parse input string containing number - return float - ''' + """parse input string containing number + return float + """ return float(raw_number) def _get_unit(self, factor, exponent, unit_type=0): - ''' based on decimal or binary factor and exponent - obtain and return correct unit - ''' + """based on decimal or binary factor and exponent + obtain and return correct unit + """ if unit_type == 0: suffix = "B" @@ -112,12 +119,11 @@ class Size(object): prefix_lst = PREFIXES_DECIMAL[unit_type] else: prefix_lst = PREFIXES_BINARY[unit_type] - return prefix_lst[exponent-1] + suffix + return prefix_lst[exponent - 1] + suffix @property def bytes(self): - ''' returns size value in bytes as int - ''' + """returns size value in bytes as int""" return int((self.factor ** self.exponent) * self.number) def _format(self, format_str, factor, exponent): @@ -129,20 +135,20 @@ class Size(object): return result def get(self, units="autobin", fmt="%0.1f %sb"): - ''' returns size value as a string with given units and format + """returns size value as a string with given units and format - "units" parameter allows to select preferred unit: - for example "KiB" or "megabytes" - accepted values are also: - "autobin" (default) - uses the highest human readable unit (binary) - "autodec" - uses the highest human readable unit (decimal) + "units" parameter allows to select preferred unit: + for example "KiB" or "megabytes" + accepted values are also: + "autobin" (default) - uses the highest human readable unit (binary) + "autodec" - uses the highest human readable unit (decimal) - "fmt" parameter allows to specify the output format: - %sb - will be replaced with the short byte size unit (e.g. MiB) - %lb - will be replaced with the long byte size unit (e.g. kilobytes) - value can be formatted using standard string replacements (e.g. %d, %f) + "fmt" parameter allows to specify the output format: + %sb - will be replaced with the short byte size unit (e.g. MiB) + %lb - will be replaced with the long byte size unit (e.g. kilobytes) + value can be formatted using standard string replacements (e.g. %d, %f) - ''' + """ ftr = BINARY_FACTOR if units == "autodec": @@ -155,6 +161,8 @@ class Size(object): exp += 1 else: ftr, exp = self._parse_units(units.strip()) - value = (float(self.factor ** self.exponent) / float(ftr ** exp)) * self.number + value = ( + float(self.factor ** self.exponent) / float(ftr ** exp) + ) * self.number return self._format(fmt, ftr, exp) % value diff --git a/tests/setup_module_utils.sh b/tests/setup_module_utils.sh deleted file mode 100755 index 94d102d..0000000 --- a/tests/setup_module_utils.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: MIT - -set -euo pipefail - -if [ -n "${DEBUG:-}" ] ; then - set -x -fi - -if [ ! -d "${1:-}" ] ; then - echo Either ansible is not installed, or there is no ansible/module_utils - echo in "$1" - Skipping - exit 0 -fi - -if [ ! -d "${2:-}" ] ; then - echo Role has no module_utils - Skipping - exit 0 -fi - -# we need absolute path for $2 -absmoddir=$( readlink -f "$2" ) - -# clean up old links to module_utils -for item in "$1"/* ; do - if lnitem=$( readlink "$item" ) && test -n "$lnitem" ; then - case "$lnitem" in - *"${2}"*) rm -f "$item" ;; - esac - fi -done - -# add new links to module_utils -for item in "$absmoddir"/* ; do - case "$item" in - *__pycache__) continue;; - *.pyc) continue;; - esac - bnitem=$( basename "$item" ) - ln -s "$item" "$1/$bnitem" -done diff --git a/tests/test-verify-volume-device.yml b/tests/test-verify-volume-device.yml index 3fb56a6..c7ba5ec 100644 --- a/tests/test-verify-volume-device.yml +++ b/tests/test-verify-volume-device.yml @@ -23,11 +23,11 @@ - name: (1/2) Process volume type (set initial value) set_fact: - st_volume_type: "{{ storage_test_volume.type }}" + st_volume_type: "{{ storage_test_volume.type }}" - name: (2/2) Process volume type (get RAID value) set_fact: - st_volume_type: "{{ storage_test_volume.raid_level }}" + st_volume_type: "{{ storage_test_volume.raid_level }}" when: storage_test_volume.type == "raid" - name: Verify the volume's device type diff --git a/tests/test-verify-volume-md.yml b/tests/test-verify-volume-md.yml index b21d8d2..27e8333 100644 --- a/tests/test-verify-volume-md.yml +++ b/tests/test-verify-volume-md.yml @@ -9,7 +9,7 @@ register: storage_test_mdadm changed_when: false - # pre-chew regex search patterns + # pre-chew regex search patterns - set_fact: storage_test_md_active_devices_re: "{{ ('Active Devices : ' ~ storage_test_volume.raid_device_count ~ '\n')|regex_escape() }}" when: storage_test_volume.raid_device_count is defined diff --git a/tests/test.yml b/tests/test.yml index 944b3cd..cb718a7 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -16,7 +16,7 @@ mount_point: '/opt/test1' - name: bar disks: ['vdc'] - #state: "absent" + # state: "absent" volumes: - name: test2 size: 8g diff --git a/tests/tests_create_lv_size_equal_to_vg.yml b/tests/tests_create_lv_size_equal_to_vg.yml index 21a5788..1737036 100644 --- a/tests/tests_create_lv_size_equal_to_vg.yml +++ b/tests/tests_create_lv_size_equal_to_vg.yml @@ -23,13 +23,13 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ lv_size }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ lv_size }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -37,12 +37,12 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - state: "absent" - volumes: - - name: test1 - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + state: "absent" + volumes: + - name: test1 + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml diff --git a/tests/tests_create_partition_volume_then_remove.yml b/tests/tests_create_partition_volume_then_remove.yml index 351b022..567f8dd 100644 --- a/tests/tests_create_partition_volume_then_remove.yml +++ b/tests/tests_create_partition_volume_then_remove.yml @@ -53,7 +53,7 @@ name: linux-system-roles.storage vars: storage_pools: - - name: "{{ unused_disks[0] }}" + - name: "{{ unused_disks[0] }}" type: partition disks: "{{ unused_disks }}" state: absent @@ -70,7 +70,7 @@ name: linux-system-roles.storage vars: storage_pools: - - name: "{{ unused_disks[0] }}" + - name: "{{ unused_disks[0] }}" type: partition disks: "{{ unused_disks }}" state: absent diff --git a/tests/tests_existing_lvm_pool.yml b/tests/tests_existing_lvm_pool.yml index 854ac0d..2490914 100644 --- a/tests/tests_existing_lvm_pool.yml +++ b/tests/tests_existing_lvm_pool.yml @@ -20,12 +20,12 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: "{{ pool_name }}" - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ volume_size }}" + storage_pools: + - name: "{{ pool_name }}" + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ volume_size }}" - include_tasks: verify-role-results.yml diff --git a/tests/tests_lvm_auto_size_cap.yml b/tests/tests_lvm_auto_size_cap.yml index 30aa6a7..eae7ff3 100644 --- a/tests/tests_lvm_auto_size_cap.yml +++ b/tests/tests_lvm_auto_size_cap.yml @@ -35,12 +35,12 @@ name: linux-system-roles.storage vars: storage_pools: - - name: foo - type: lvm - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ doubled_size.stdout|trim }}" + - name: foo + type: lvm + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ doubled_size.stdout|trim }}" - name: unreachable task fail: msg: UNREACH @@ -58,11 +58,11 @@ name: linux-system-roles.storage vars: storage_pools: - - name: foo - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ test_disk_size }}" + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ test_disk_size }}" - include_tasks: verify-role-results.yml @@ -71,12 +71,12 @@ name: linux-system-roles.storage vars: storage_pools: - - name: foo - type: lvm - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ test_disk_size }}" + - name: foo + type: lvm + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ test_disk_size }}" - include_tasks: verify-role-results.yml @@ -85,7 +85,7 @@ name: linux-system-roles.storage vars: storage_pools: - - name: foo - disks: "{{ unused_disks }}" - state: absent - volumes: [] + - name: foo + disks: "{{ unused_disks }}" + state: absent + volumes: [] diff --git a/tests/tests_lvm_one_disk_one_volume.yml b/tests/tests_lvm_one_disk_one_volume.yml index b1096cf..6452f54 100644 --- a/tests/tests_lvm_one_disk_one_volume.yml +++ b/tests/tests_lvm_one_disk_one_volume.yml @@ -19,13 +19,13 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ volume_size }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ volume_size }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -33,13 +33,13 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - volumes: - - name: test1 - size: "{{ volume_size }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + volumes: + - name: test1 + size: "{{ volume_size }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -47,14 +47,14 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - state: absent - volumes: - - name: test1 - size: "{{ volume_size }}" - mount_point: "{{ mount_location }}" - state: absent + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + state: absent + volumes: + - name: test1 + size: "{{ volume_size }}" + mount_point: "{{ mount_location }}" + state: absent - include_tasks: verify-role-results.yml diff --git a/tests/tests_misc.yml b/tests/tests_misc.yml index 3139bc7..afe753a 100644 --- a/tests/tests_misc.yml +++ b/tests/tests_misc.yml @@ -197,7 +197,7 @@ block: - name: Try to mount swap filesystem to "{{ mount_location }}" include_role: - name: linux-system-roles.storage + name: linux-system-roles.storage vars: storage_volumes: - name: test1 diff --git a/tests/tests_null_raid_pool.yml b/tests/tests_null_raid_pool.yml index 2b7b9f3..5c3c785 100644 --- a/tests/tests_null_raid_pool.yml +++ b/tests/tests_null_raid_pool.yml @@ -31,9 +31,9 @@ raid_level: "null" state: present volumes: - - name: lv1 - size: "{{ volume1_size }}" - mount_point: "{{ mount_location1 }}" + - name: lv1 + size: "{{ volume1_size }}" + mount_point: "{{ mount_location1 }}" - name: get existing raids (after run) command: "cat /proc/mdstat" @@ -52,12 +52,12 @@ raid_level: "null" state: absent volumes: - - name: lv1 - size: "{{ volume1_size }}" - mount_point: "{{ mount_location1 }}" + - name: lv1 + size: "{{ volume1_size }}" + mount_point: "{{ mount_location1 }}" - name: compare mdstat results assert: that: - - storage_test_mdstat1.stdout == storage_test_mdstat2.stdout + - storage_test_mdstat1.stdout == storage_test_mdstat2.stdout msg: "Raid created when it should not be" diff --git a/tests/tests_resize.yml b/tests/tests_resize.yml index 209d129..4fd8583 100644 --- a/tests/tests_resize.yml +++ b/tests/tests_resize.yml @@ -29,16 +29,16 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - type: lvm - volumes: - - name: test1 - # resizing is currently supported only for ext2/3/4 - fs_type: 'ext4' - size: "{{ volume_size_before }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + type: lvm + volumes: + - name: test1 + # resizing is currently supported only for ext2/3/4 + fs_type: 'ext4' + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -46,15 +46,15 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - type: lvm - disks: "{{ unused_disks }}" - volumes: - - name: test1 - fs_type: 'ext4' - size: "{{ volume_size_after }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + type: lvm + disks: "{{ unused_disks }}" + volumes: + - name: test1 + fs_type: 'ext4' + size: "{{ volume_size_after }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -194,14 +194,14 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - state: absent - volumes: - - name: test1 - size: "{{ volume_size_before }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + state: absent + volumes: + - name: test1 + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -259,14 +259,14 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - state: absent - volumes: - - name: test1 - size: "{{ volume_size_before }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + state: absent + volumes: + - name: test1 + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml @@ -324,13 +324,13 @@ include_role: name: linux-system-roles.storage vars: - storage_pools: - - name: foo - disks: "{{ unused_disks }}" - state: absent - volumes: - - name: test1 - size: "{{ volume_size_before }}" - mount_point: "{{ mount_location }}" + storage_pools: + - name: foo + disks: "{{ unused_disks }}" + state: absent + volumes: + - name: test1 + size: "{{ volume_size_before }}" + mount_point: "{{ mount_location }}" - include_tasks: verify-role-results.yml diff --git a/tests/unit/bsize_test.py b/tests/unit/bsize_test.py index f88a9c1..fae0f5f 100644 --- a/tests/unit/bsize_test.py +++ b/tests/unit/bsize_test.py @@ -1,7 +1,12 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + import pytest from storage_lsr.size import Size + def test_bsize(): # check failure on incorrect string with pytest.raises(ValueError) as e: diff --git a/tests/unit/gensym_test.py b/tests/unit/gensym_test.py index 6d164dc..fd00ddf 100644 --- a/tests/unit/gensym_test.py +++ b/tests/unit/gensym_test.py @@ -1,68 +1,115 @@ #!/usr/bin/python """This module tests methods defined in the lvm_gensym.py module using the pytest framework""" -import pytest - +from __future__ import absolute_import, division, print_function -import lvm_gensym +__metaclass__ = type +import pytest -used_lv_names = ['root', 'root_0', 'root_1', 'root_2', 'root_3', 'swap_0', 'swap', 'swap_1'] -test_lv_names = [{'fs_type': 'ext', 'mount': '/'}, - {'fs_type': 'zfs', 'mount': '/home/user'}, - {'fs_type': 'swap', 'mount': ''} - ] +import lvm_gensym -used_vg_names = ['linux_host', 'rhel_user0', 'rhel_0_user'] -test_vg_names = ['rhel_user', 'rhel_user_0', 'rhel_user_1', - 'rhel_user_2', 'rhel_user_3', 'linux_user', - 'fedora_user', 'fedora_user_0', 'fedora_user_1' - ] +used_lv_names = [ + "root", + "root_0", + "root_1", + "root_2", + "root_3", + "swap_0", + "swap", + "swap_1", +] + +test_lv_names = [ + {"fs_type": "ext", "mount": "/"}, + {"fs_type": "zfs", "mount": "/home/user"}, + {"fs_type": "swap", "mount": ""}, +] + +used_vg_names = ["linux_host", "rhel_user0", "rhel_0_user"] + +test_vg_names = [ + "rhel_user", + "rhel_user_0", + "rhel_user_1", + "rhel_user_2", + "rhel_user_3", + "linux_user", + "fedora_user", + "fedora_user_0", + "fedora_user_1", +] + +lvm_facts = { + "lvs": { + "Home": "", + "Swap": "", + "Root": "", + "Root_0": "", + "root": "", + "root_0": "", + "swap": "", + "swap_0": "", + "swap_1": "", + }, + "vgs": {"rhel_user": "", "rhel_user_0": "", "rhel_user_1": ""}, +} -lvm_facts = {'lvs': {'Home': '', 'Swap': '', 'Root': '', - 'Root_0': '', 'root': '', 'root_0': '', - 'swap': '', 'swap_0': '', 'swap_1': '', - }, - 'vgs': {'rhel_user': '', 'rhel_user_0': '', 'rhel_user_1': ''} - } def test_unique_base_name(): """Test whether the returned name is unique using a supplied list of test names""" - assert lvm_gensym.get_unique_name_from_base('root', used_lv_names) == 'root_4' - assert lvm_gensym.get_unique_name_from_base('rhel_user', test_vg_names) == 'rhel_user_4' + assert lvm_gensym.get_unique_name_from_base("root", used_lv_names) == "root_4" + assert ( + lvm_gensym.get_unique_name_from_base("rhel_user", test_vg_names) + == "rhel_user_4" + ) + def test_return_val(): """Verify that a supplied unique name and a list of used names returns True""" for (index, name) in enumerate(test_vg_names): assert lvm_gensym.name_is_unique(name[index], used_vg_names) + def test_get_base_vg_name(): """Check generated base volume group name against the expected base name""" - assert lvm_gensym.get_vg_name_base('hostname', 'rhel') == 'rhel_hostname' + assert lvm_gensym.get_vg_name_base("hostname", "rhel") == "rhel_hostname" + @pytest.mark.parametrize("os_name", ["foo", "bar", "baz"]) def test_vg_eval(monkeypatch, os_name): """Check generated unique volume group name against the expected name""" + def get_os_name(): return os_name vg_names = [os_name + "_user", os_name + "_user_0", os_name + "_user_1"] _lvm_facts = dict(vgs=dict.fromkeys(vg_names), lvs=dict()) monkeypatch.setattr(lvm_gensym, "get_os_name", get_os_name) - assert lvm_gensym.get_vg_name('user', _lvm_facts) == os_name + '_user_2' - assert lvm_gensym.get_vg_name('', _lvm_facts) == os_name + assert lvm_gensym.get_vg_name("user", _lvm_facts) == os_name + "_user_2" + assert lvm_gensym.get_vg_name("", _lvm_facts) == os_name + def test_lv_eval(): """Test the generated unique logical volume name against the expected name""" - expected = ['root_1', 'home_user', 'swap_2'] + expected = ["root_1", "home_user", "swap_2"] for (ctr, name_inputs) in enumerate(test_lv_names): - assert lvm_gensym.get_lv_name(name_inputs['fs_type'], name_inputs['mount'], lvm_facts) == expected[ctr] + assert ( + lvm_gensym.get_lv_name( + name_inputs["fs_type"], name_inputs["mount"], lvm_facts + ) + == expected[ctr] + ) + def test_get_base_lv_name(): """Test the generated base logical volume name against the expected name""" - expected = ['root', 'home_user', 'swap'] + expected = ["root", "home_user", "swap"] for (ctr, names_input) in enumerate(test_lv_names): - assert lvm_gensym.get_lv_name_base(names_input['fs_type'], names_input['mount']) == expected[ctr] + assert ( + lvm_gensym.get_lv_name_base(names_input["fs_type"], names_input["mount"]) + == expected[ctr] + ) diff --git a/tests/unit/resolve_blockdev_test.py b/tests/unit/resolve_blockdev_test.py index 0eafe7b..ad50628 100644 --- a/tests/unit/resolve_blockdev_test.py +++ b/tests/unit/resolve_blockdev_test.py @@ -1,3 +1,6 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type import os import pytest @@ -5,73 +8,80 @@ import pytest import resolve_blockdev -blkid_data = [('LABEL=target', '/dev/sdx3'), - ('UUID=6c75fa75-e5ab-4a12-a567-c8aa0b4b60a5', '/dev/sdaz'), - ('LABEL=missing', '')] +blkid_data = [ + ("LABEL=target", "/dev/sdx3"), + ("UUID=6c75fa75-e5ab-4a12-a567-c8aa0b4b60a5", "/dev/sdaz"), + ("LABEL=missing", ""), +] -path_data = ['/dev/md/unreal', - '/dev/mapper/fakevg-fakelv', - '/dev/adisk', - '/dev/disk/by-id/wwn-0x123456789abc'] +path_data = [ + "/dev/md/unreal", + "/dev/mapper/fakevg-fakelv", + "/dev/adisk", + "/dev/disk/by-id/wwn-0x123456789abc", +] -canonical_paths = {"/dev/sda": "/dev/sda", - "/dev/dm-3": "/dev/mapper/vg_system-lv_data", - "/dev/md127": "/dev/md/userdb", - "/dev/notfound": ""} +canonical_paths = { + "/dev/sda": "/dev/sda", + "/dev/dm-3": "/dev/mapper/vg_system-lv_data", + "/dev/md127": "/dev/md/userdb", + "/dev/notfound": "", +} -@pytest.mark.parametrize('spec,device', blkid_data) +@pytest.mark.parametrize("spec,device", blkid_data) def test_key_value_pair(spec, device, monkeypatch): def run_cmd(args): for _spec, _dev in blkid_data: if _spec in args: break else: - _dev = '' - return (0, _dev, '') + _dev = "" + return (0, _dev, "") - monkeypatch.setattr(os.path, 'exists', lambda p: True) + monkeypatch.setattr(os.path, "exists", lambda p: True) assert resolve_blockdev.resolve_blockdev(spec, run_cmd) == device -@pytest.mark.parametrize('name', [os.path.basename(p) for p in path_data]) +@pytest.mark.parametrize("name", [os.path.basename(p) for p in path_data]) def test_device_names(name, monkeypatch): """ Test return values for basename specs, assuming all paths are real. """ + def path_exists(path): return next((data for data in path_data if data == path), False) - expected = next((data for data in path_data if os.path.basename(data) == name), '') - monkeypatch.setattr(os.path, 'exists', path_exists) + expected = next((data for data in path_data if os.path.basename(data) == name), "") + monkeypatch.setattr(os.path, "exists", path_exists) assert resolve_blockdev.resolve_blockdev(name, None) == expected def test_device_name(monkeypatch): - assert os.path.exists('/dev/xxx') is False + assert os.path.exists("/dev/xxx") is False - monkeypatch.setattr(os.path, 'exists', lambda p: True) - assert resolve_blockdev.resolve_blockdev('xxx', None) == '/dev/xxx' + monkeypatch.setattr(os.path, "exists", lambda p: True) + assert resolve_blockdev.resolve_blockdev("xxx", None) == "/dev/xxx" - monkeypatch.setattr(os.path, 'exists', lambda p: False) - assert resolve_blockdev.resolve_blockdev('xxx', None) == '' + monkeypatch.setattr(os.path, "exists", lambda p: False) + assert resolve_blockdev.resolve_blockdev("xxx", None) == "" def test_full_path(monkeypatch): path = "/dev/idonotexist" - monkeypatch.setattr(os.path, 'exists', lambda p: True) + monkeypatch.setattr(os.path, "exists", lambda p: True) assert resolve_blockdev.resolve_blockdev(path, None) == path - monkeypatch.setattr(os.path, 'exists', lambda p: False) - assert resolve_blockdev.resolve_blockdev(path, None) == '' + monkeypatch.setattr(os.path, "exists", lambda p: False) + assert resolve_blockdev.resolve_blockdev(path, None) == "" path = "/dev/disk/by-label/alabel" - monkeypatch.setattr(os.path, 'exists', lambda p: True) + monkeypatch.setattr(os.path, "exists", lambda p: True) assert resolve_blockdev.resolve_blockdev(path, None) == path - monkeypatch.setattr(os.path, 'exists', lambda p: False) - assert resolve_blockdev.resolve_blockdev(path, None) == '' + monkeypatch.setattr(os.path, "exists", lambda p: False) + assert resolve_blockdev.resolve_blockdev(path, None) == "" -@pytest.mark.parametrize('device', list(canonical_paths.keys())) +@pytest.mark.parametrize("device", list(canonical_paths.keys())) def test_canonical_path(device, monkeypatch): def _get_name(device): name = os.path.basename(canonical_paths[device]) @@ -79,8 +89,8 @@ def test_canonical_path(device, monkeypatch): raise Exception("failed to find name") return name - monkeypatch.setattr(resolve_blockdev, '_get_dm_name_from_kernel_dev', _get_name) - monkeypatch.setattr(resolve_blockdev, '_get_md_name_from_kernel_dev', _get_name) + monkeypatch.setattr(resolve_blockdev, "_get_dm_name_from_kernel_dev", _get_name) + monkeypatch.setattr(resolve_blockdev, "_get_md_name_from_kernel_dev", _get_name) canonical = canonical_paths[device] if canonical: diff --git a/tests/unit/test_unused_disk.py b/tests/unit/test_unused_disk.py index a4339c4..493b4b0 100644 --- a/tests/unit/test_unused_disk.py +++ b/tests/unit/test_unused_disk.py @@ -1,72 +1,91 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + import pytest import find_unused_disk import os -blkid_data_pttype = [('/dev/sdx', '/dev/sdx: PTTYPE=\"dos\"'), - ('/dev/sdy', '/dev/sdy: PTTYPE=\"test\"')] +blkid_data_pttype = [ + ("/dev/sdx", '/dev/sdx: PTTYPE="dos"'), + ("/dev/sdy", '/dev/sdy: PTTYPE="test"'), +] -blkid_data = [('/dev/sdx', 'UUID=\"hello-1234-56789\" TYPE=\"crypto_LUKS\"'), - ('/dev/sdy', 'UUID=\"this-1s-a-t3st-f0r-ansible\" VERSION=\"LVM2 001\" TYPE=\"LVM2_member\" USAGE=\"raid\"'), - ('/dev/sdz', 'LABEL=\"/data\" UUID=\"a12bcdef-345g-67h8-90i1-234j56789k10\" VERSION=\"1.0\" TYPE=\"ext4\" USAGE=\"filesystem\"')] +blkid_data = [ + ("/dev/sdx", 'UUID="hello-1234-56789" TYPE="crypto_LUKS"'), + ( + "/dev/sdy", + 'UUID="this-1s-a-t3st-f0r-ansible" VERSION="LVM2 001" TYPE="LVM2_member" USAGE="raid"', + ), + ( + "/dev/sdz", + 'LABEL="/data" UUID="a12bcdef-345g-67h8-90i1-234j56789k10" VERSION="1.0" TYPE="ext4" USAGE="filesystem"', + ), +] -holders_data_none = [('/dev/sdx', ''), - ('/dev/dm-99', '')] +holders_data_none = [("/dev/sdx", ""), ("/dev/dm-99", "")] -holders_data = [('/dev/sdx', 'dm-0'), - ('/dev/dm-99', 'dm-2 dm-3 dm-4')] +holders_data = [("/dev/sdx", "dm-0"), ("/dev/dm-99", "dm-2 dm-3 dm-4")] -@pytest.mark.parametrize('disk, blkid', blkid_data_pttype) +@pytest.mark.parametrize("disk, blkid", blkid_data_pttype) def test_no_signature_true(disk, blkid): def run_command(args): - return [0, blkid, ''] + return [0, blkid, ""] + assert find_unused_disk.no_signature(run_command, disk) is True -@pytest.mark.parametrize('disk, blkid', blkid_data) +@pytest.mark.parametrize("disk, blkid", blkid_data) def test_no_signature_false(disk, blkid): def run_command(args): - return [0, blkid, ''] + return [0, blkid, ""] + assert find_unused_disk.no_signature(run_command, disk) is False -@pytest.mark.parametrize('disk, holders', holders_data_none) +@pytest.mark.parametrize("disk, holders", holders_data_none) def test_no_holders_true(disk, holders, monkeypatch): def mock_return(args): return holders - monkeypatch.setattr(os, 'listdir', mock_return) + + monkeypatch.setattr(os, "listdir", mock_return) assert find_unused_disk.no_holders(disk) is True -@pytest.mark.parametrize('disk, holders', holders_data) +@pytest.mark.parametrize("disk, holders", holders_data) def test_no_holders_false(disk, holders, monkeypatch): def mock_return(args): return holders - monkeypatch.setattr(os, 'listdir', mock_return) + + monkeypatch.setattr(os, "listdir", mock_return) assert find_unused_disk.no_holders(disk) is False def test_can_open_true(monkeypatch): def mock_return(args, flag): return True - monkeypatch.setattr(os, 'open', mock_return) - assert find_unused_disk.can_open('/hello') is True + + monkeypatch.setattr(os, "open", mock_return) + assert find_unused_disk.can_open("/hello") is True def test_can_open_false(monkeypatch): def mock_return(args, flag): raise OSError - monkeypatch.setattr(os, 'open', mock_return) - assert find_unused_disk.can_open('/hello') is False + + monkeypatch.setattr(os, "open", mock_return) + assert find_unused_disk.can_open("/hello") is False def test_is_ignored(monkeypatch): def mock_realpath(path): return path - monkeypatch.setattr(os.path, 'realpath', mock_realpath) - assert find_unused_disk.is_ignored('/dev/sda') is False - assert find_unused_disk.is_ignored('/dev/vda') is False - assert find_unused_disk.is_ignored('/dev/mapper/mpatha') is False - assert find_unused_disk.is_ignored('/dev/md/Volume0') is False - assert find_unused_disk.is_ignored('/dev/nullb0') is True + + monkeypatch.setattr(os.path, "realpath", mock_realpath) + assert find_unused_disk.is_ignored("/dev/sda") is False + assert find_unused_disk.is_ignored("/dev/vda") is False + assert find_unused_disk.is_ignored("/dev/mapper/mpatha") is False + assert find_unused_disk.is_ignored("/dev/md/Volume0") is False + assert find_unused_disk.is_ignored("/dev/nullb0") is True diff --git a/tox.ini b/tox.ini index 92482d5..91c22a8 100644 --- a/tox.ini +++ b/tox.ini @@ -13,9 +13,3 @@ configfile = .ansible-lint setenv = RUN_PYTEST_SETUP_MODULE_UTILS = true RUN_PYLINT_SETUP_MODULE_UTILS = true - -[testenv:black] -commands = bash -c 'echo black is currently not enabled - please fix this' - -[testenv:flake8] -commands = bash -c 'echo flake8 is currently not enabled - please fix this' -- 2.30.2