← Back to team overview

sts-sponsors team mailing list archive

[Merge] ~alexsander-souza/maas:sles_support into maas:master

 

Alexsander de Souza has proposed merging ~alexsander-souza/maas:sles_support into maas:master.

Commit message:
add SLES support

adds support for SUSE Enterprise Linux Server versions 12 and 15

Requested reviews:
  MAAS Maintainers (maas-maintainers)

For more details, see:
https://code.launchpad.net/~alexsander-souza/maas/+git/maas/+merge/436100
-- 
Your team MAAS Maintainers is requested to review the proposed merge of ~alexsander-souza/maas:sles_support into maas:master.
diff --git a/src/maasserver/preseed_storage.py b/src/maasserver/preseed_storage.py
index 2a0b0ce..f2ee630 100644
--- a/src/maasserver/preseed_storage.py
+++ b/src/maasserver/preseed_storage.py
@@ -450,10 +450,26 @@ class CurtinStorageGenerator:
         for filesystem in self.operations["format"]:
             self._generate_format_operation(filesystem)
 
+    def _ext4_has_metadata_csum(self):
+        """Older distros don't have Metadata Checksum, and enabling it when
+        it's not supported prevents Linux from mounting this partition
+        for writing"""
+        if self.node.osystem == "suse":
+            return not self.node.distro_series.startswith("sles12")
+        return True
+
     def _generate_format_operation(self, filesystem):
         """Generate format operation for `filesystem` and place in
         `storage_config`."""
         device_or_partition = filesystem.get_device()
+        extra = {}
+
+        if (
+            filesystem.fstype == FILESYSTEM_TYPE.EXT4
+            and not self._ext4_has_metadata_csum()
+        ):
+            extra["extra_options"] = ["-O", "^metadata_csum"]
+
         self.storage_config.append(
             {
                 "id": "%s_format" % device_or_partition.get_name(),
@@ -462,6 +478,7 @@ class CurtinStorageGenerator:
                 "uuid": filesystem.uuid,
                 "label": filesystem.label,
                 "volume": device_or_partition.get_name(),
+                **extra,
             }
         )
 
diff --git a/src/maasserver/tests/test_preseed_storage.py b/src/maasserver/tests/test_preseed_storage.py
index 625614a..65fbec5 100644
--- a/src/maasserver/tests/test_preseed_storage.py
+++ b/src/maasserver/tests/test_preseed_storage.py
@@ -135,6 +135,77 @@ class TestSpecialFilesystems(MAASServerTestCase, AssertStorageConfigMixin):
         self.assertStorageConfig(self.STORAGE_CONFIG, config)
 
 
+class TestExt4MetadataCSUM(MAASServerTestCase, AssertStorageConfigMixin):
+
+    STORAGE_CONFIG = dedent(
+        """\
+        config:
+          - grub_device: true
+            id: sda
+            model: QEMU HARDDISK
+            name: sda
+            ptable: gpt
+            serial: QM00001
+            type: disk
+            wipe: superblock
+          - device: sda
+            id: sda-part1
+            name: sda-part1
+            number: 1
+            offset: 4194304B
+            size: 5897191424B
+            type: partition
+            uuid: f74ff260-2a5b-4a36-b1b8-37f746b946bf
+            wipe: superblock
+          - fstype: ext4
+            id: sda-part1_format
+            label: null
+            type: format
+            uuid: bf34f38c-02b7-4b4b-bb7c-e73521f9ead7
+            volume: sda-part1
+            extra_options:
+              - -O
+              - ^metadata_csum
+          - device: sda-part1_format
+            id: sda-part1_mount
+            path: /
+            type: mount
+    """
+    )
+
+    def test_renders_expected_output(self):
+        node = factory.make_Node(
+            with_boot_disk=False, osystem="suse", distro_series="sles12.5"
+        )
+        boot_disk = factory.make_PhysicalBlockDevice(
+            node=node,
+            size=8 * 1024**3,
+            name="sda",
+            model="QEMU HARDDISK",
+            serial="QM00001",
+        )
+        partition_table = factory.make_PartitionTable(
+            table_type=PARTITION_TABLE_TYPE.GPT, block_device=boot_disk
+        )
+        root_partition = factory.make_Partition(
+            partition_table=partition_table,
+            uuid="f74ff260-2a5b-4a36-b1b8-37f746b946bf",
+            size=(5.5 * 1024**3) - PARTITION_TABLE_EXTRA_SPACE,
+            bootable=False,
+        )
+        factory.make_Filesystem(
+            uuid="bf34f38c-02b7-4b4b-bb7c-e73521f9ead7",
+            node_config=node.current_config,
+            fstype=FILESYSTEM_TYPE.EXT4,
+            partition=root_partition,
+            mount_options=None,
+            mount_point="/",
+        )
+        node._create_acquired_filesystems()
+        config = compose_curtin_storage_config(node)
+        self.assertStorageConfig(self.STORAGE_CONFIG, config)
+
+
 class TestSimpleGPTLayout(MAASServerTestCase, AssertStorageConfigMixin):
 
     STORAGE_CONFIG = dedent(
diff --git a/src/provisioningserver/drivers/osystem/suse.py b/src/provisioningserver/drivers/osystem/suse.py
index c6b21d7..8eac7d3 100644
--- a/src/provisioningserver/drivers/osystem/suse.py
+++ b/src/provisioningserver/drivers/osystem/suse.py
@@ -3,16 +3,26 @@
 
 """SUSE Operating System."""
 
+import re
 
 from provisioningserver.drivers.osystem import (
     BOOT_IMAGE_PURPOSE,
     OperatingSystem,
 )
 
-DISTRO_SERIES_CHOICES = {"opensuse13": "openSUSE 13.1"}
+DISTRO_MATCHER = re.compile(
+    r"^(?P<product>sles|opensuse|tumbleweed)(?P<major>\d+)?(\.(?P<minor>\d+))?(-(?P<title>.+))?$",
+    re.I,
+)
+
+SUSE_PRODUCTS = {
+    "sles": "SUSE Linux Enterprise Server",
+    "opensuse": "OpenSUSE",
+    "tumbleweed": "OpenSUSE Tumbleweed",
+}
+
 
-DISTRO_SERIES_DEFAULT = "opensuse13"
-assert DISTRO_SERIES_DEFAULT in DISTRO_SERIES_CHOICES
+DISTRO_SERIES_DEFAULT = "tumbleweed"
 
 
 class SUSEOS(OperatingSystem):
@@ -27,7 +37,8 @@ class SUSEOS(OperatingSystem):
 
     def is_release_supported(self, release):
         """Return True when the release is supported, False otherwise."""
-        return release in DISTRO_SERIES_CHOICES
+        matched = DISTRO_MATCHER.match(release)
+        return matched is not None
 
     def get_default_release(self):
         """Gets the default release to use when a release is not
@@ -36,4 +47,23 @@ class SUSEOS(OperatingSystem):
 
     def get_release_title(self, release):
         """Return the title for the given release."""
-        return DISTRO_SERIES_CHOICES.get(release)
+        matched = DISTRO_MATCHER.match(release)
+        if matched is None:
+            return f"{self.title} {release}"
+
+        prod = matched.group("product")
+        major = matched.group("major")
+        minor = matched.group("minor")
+        title = matched.group("title")
+
+        ret = SUSE_PRODUCTS[prod]
+        if major is not None:
+            ret = f"{ret} {major}"
+        if minor is not None:
+            if prod == "sles":
+                ret = f"{ret} SP{minor}"
+            else:
+                ret = f"{ret}.{minor}"
+        if title is not None:
+            ret = f"{ret} {title}"
+        return ret
diff --git a/src/provisioningserver/drivers/osystem/tests/test_suse.py b/src/provisioningserver/drivers/osystem/tests/test_suse.py
index 7f2bd4c..c0d2753 100644
--- a/src/provisioningserver/drivers/osystem/tests/test_suse.py
+++ b/src/provisioningserver/drivers/osystem/tests/test_suse.py
@@ -5,13 +5,11 @@
 
 
 from itertools import product
-import random
 
 from maastesting.factory import factory
 from maastesting.testcase import MAASTestCase
 from provisioningserver.drivers.osystem.suse import (
     BOOT_IMAGE_PURPOSE,
-    DISTRO_SERIES_CHOICES,
     DISTRO_SERIES_DEFAULT,
     SUSEOS,
 )
@@ -40,7 +38,16 @@ class TestSUSEOS(MAASTestCase):
 
     def test_get_release_title(self):
         osystem = SUSEOS()
-        release = random.choice(list(DISTRO_SERIES_CHOICES))
-        self.assertEqual(
-            DISTRO_SERIES_CHOICES[release], osystem.get_release_title(release)
-        )
+        cases = [
+            ("sles", "SUSE Linux Enterprise Server"),
+            ("sles12", "SUSE Linux Enterprise Server 12"),
+            ("sles15.4", "SUSE Linux Enterprise Server 15 SP4"),
+            ("opensuse15", "OpenSUSE 15"),
+            ("opensuse15.4", "OpenSUSE 15.4"),
+            ("tumbleweed", "OpenSUSE Tumbleweed"),
+            ("tumbleweed-20230101", "OpenSUSE Tumbleweed 20230101"),
+        ]
+        for release, title in cases:
+            self.assertEqual(
+                title, osystem.get_release_title(release), release
+            )
diff --git a/src/provisioningserver/templates/uefi/config.local.amd64.template b/src/provisioningserver/templates/uefi/config.local.amd64.template
index 7cfc382..219a2af 100644
--- a/src/provisioningserver/templates/uefi/config.local.amd64.template
+++ b/src/provisioningserver/templates/uefi/config.local.amd64.template
@@ -14,6 +14,8 @@ menuentry 'Local' {
             redhat/grubx64.efi \
             rhel/shimx64.efi \
             rhel/grubx64.efi \
+            suse/shim.efi \
+            suse/grubx64.efi \
             red/grubx64.efi \
             Microsoft/Boot/bootmgfw.efi; do
         search --set=root --file /efi/$bootloader

Follow ups