yast/yast-storage-ng

View on GitHub
src/lib/y2storage/storage_feature.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Copyright (c) [2016-2023] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "yast"
require "storage"
require "y2storage/feature"

module Y2Storage
  #
  # Class representing the storage features defined by libstorage-ng
  #
  # In libstorage-ng each feature is represented by a bit-mask identified
  # by a constant with name UF_XXX (with XXX being the name of the feature).
  # A set of features is represented by a bit-field of those masks.
  #
  # Thus, one of those bit-fields is used to specify which features are
  # used in the current target machine's storage setup. Additionally, a similar
  # bit-field is used to report features that have been detected in the system
  # but that cannot be probed because some command is missing.
  #
  # This class adds object orientation of top of that, each instance of
  # StorageFeature represents a concrete feature and offers methods to know
  # which add-on packages would be needed so support that feature, so they
  # can be installed or marked for installation as needed.
  #
  class StorageFeature < Feature
    #======================================================================
    # Configurable part starts here
    #
    # Software packages required for storage features.
    # Any map value may be a string or a list of strings.
    #
    # Packages that are part of a minimal installation (e.g., "util-linux")
    # are not listed here.
    #
    # Those features correspond directly to the enum defined in
    # https://github.com/openSUSE/libstorage-ng/blob/master/storage/UsedFeatures.h
    #
    FEATURE_PACKAGES =
      {
        # SUSE standard technologies
        UF_LVM:              "lvm2",

        # RAID technologies and related
        UF_MULTIPATH:        ["device-mapper", "multipath-tools"],
        UF_DMRAID:           ["device-mapper", "dmraid"],
        UF_MDRAID:           "mdadm",

        # Btrfs needs e2fsprogs for 'lsattr' and 'chattr' to check for CoW
        UF_BTRFS:            ["btrfsprogs", "e2fsprogs"],

        # Other filesystems
        UF_EXT2:             "e2fsprogs",
        UF_EXT3:             "e2fsprogs",
        UF_EXT4:             "e2fsprogs",
        UF_XFS:              "xfsprogs",
        UF_REISERFS:         "reiserfs",
        UF_NILFS2:           "nilfs-utils",
        UF_NFS:              "nfs-client",
        UF_NTFS:             ["ntfs-3g", "ntfsprogs"],
        UF_VFAT:             "dosfstools",
        UF_EXFAT:            "exfatprogs",
        UF_F2FS:             "f2fs-tools",
        UF_UDF:              "udftools",
        UF_JFS:              "jfsutils",
        UF_SWAP:             [],

        # Crypto technologies
        UF_PLAIN_ENCRYPTION: "cryptsetup",
        UF_BITLOCKER:        [],
        # Device mapper is needed if names like /dev/mapper/cr_root are used at boot
        UF_LUKS:             ["device-mapper", "cryptsetup"],

        # Data transport methods
        UF_ISCSI:            "open-iscsi",
        UF_FCOE:             "fcoe-utils",
        UF_FC:               [],
        UF_DASD:             [],
        UF_PMEM:             [],
        UF_NVME:             "nvme-cli",

        # Other
        UF_QUOTA:            "quota",
        UF_BCACHE:           "bcache-tools",
        UF_BCACHEFS:         [], # When implemented: "bcachefs-tools"
        UF_SNAPSHOTS:        "snapper"
      }

    # Storage-related packages that are nice to have, but not absolutely
    # required.
    #
    # SLES-12 for example (unlike SLED-12) does not come with NTFS packages,
    # so they cannot be installed. But there might already be an existing
    # NTFS Windows partition on the disk; don't throw an error pop-up in that
    # case, just log a warning (bsc#1039830).
    #
    OPTIONAL_PACKAGES = ["ntfs-3g", "ntfsprogs", "exfat-utils", "f2fs-tools", "jfsutils", "nilfs-utils"]
    # configurable part ends here
    #======================================================================

    # All known libstorage-ng features
    #
    # @return [Array<StorageFeature>]
    def self.all
      @all ||= FEATURE_PACKAGES.map do |id, pkg_names|
        packages = Array(pkg_names).map do |pkg|
          Package.new(pkg, optional: OPTIONAL_PACKAGES.include?(pkg))
        end
        new(id, packages)
      end
    end

    # Drop the cache of packages for all known storage features
    #
    # This is only ever needed if the available packages might have changed
    # since the last use of this class.
    def self.drop_cache
      all.each(&:drop_cache)
    end

    # Constructor
    #
    # This looks up a constant in the ::Storage namespace to make sure the id
    # is known to libstorage-ng.
    #
    # @raise [NameError] if no constant for this feature is defined in libstorage-ng
    #
    # @param id [Symbol] see {#id}
    # @param packages [Array<Package>] see {#all_packages}
    def initialize(id, packages)
      super

      # Raising a NameError exception as soon as possible (i.e. in the constructor)
      # is a good way to make sure we are in sync with libstorage-ng regarding
      # the definition of possible features
      @bitmask = ::Storage.const_get(id)
    end

    # Whether the feature is included in the given bit-field
    #
    # @param bitfield [Integer]
    # @return [Boolean]
    def in_bitfield?(bitfield)
      (bitfield & bitmask) == bitmask
    end

    private

    # Bitmask for a storage feature
    #
    # This looks up a constant in the ::Storage (libstorage-ng) namespace with
    # the id of the feature (one of the enum values in UsedFeatures.h).
    #
    # @return [Integer]
    attr_reader :bitmask
  end
end