diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ddec5bbb..775a5c8ee7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG **ENHANCEMENTS** - Improve cluster update resiliency on login nodes by reusing the head-node-driven orchestration already in place on compute nodes, removing the dependency on cfn-hup and cfn-init. +- Add support for AlmaLinux 8 as a `CustomAmi` created through the `build-image` process. ParallelCluster does not + publish an official AlmaLinux 8 AMI. **CHANGES** - The validator `ClusterNameValidator` now enforces cluster names to be limited to 40 characters when using `ExternalSlurmdbd`, diff --git a/cli/src/pcluster/constants.py b/cli/src/pcluster/constants.py index e4a0d774ba..8bc755b57f 100644 --- a/cli/src/pcluster/constants.py +++ b/cli/src/pcluster/constants.py @@ -32,9 +32,18 @@ "rocky8", "rhel9", "rocky9", + "almalinux8", ] -UNSUPPORTED_OSES_FOR_MICRO_NANO = ["ubuntu2204", "ubuntu2404", "rhel8", "rocky8", "rhel9", "rocky9"] -UNSUPPORTED_OSES_FOR_P6E_GB200 = ["rhel8", "rocky8", "rhel9"] +UNSUPPORTED_OSES_FOR_MICRO_NANO = [ + "ubuntu2204", + "ubuntu2404", + "rhel8", + "rocky8", + "rhel9", + "rocky9", + "almalinux8", +] +UNSUPPORTED_OSES_FOR_P6E_GB200 = ["rhel8", "rocky8", "rhel9", "almalinux8"] SUPPORTED_OSES_FOR_P6E_GB200 = list(set(SUPPORTED_OSES) - set(UNSUPPORTED_OSES_FOR_P6E_GB200)) UNSUPPORTED_OSES_FOR_P6_B300 = [] SUPPORTED_OSES_FOR_P6_B300 = list(set(SUPPORTED_OSES) - set(UNSUPPORTED_OSES_FOR_P6_B300)) @@ -65,6 +74,7 @@ "rocky8": CR_PLATFORM_LINUX_UNIX, "rhel9": CR_PLATFORM_RHEL, "rocky9": CR_PLATFORM_LINUX_UNIX, + "almalinux8": CR_PLATFORM_LINUX_UNIX, } OS_MAPPING = { @@ -75,6 +85,7 @@ "rocky8": {"user": "rocky"}, "rhel9": {"user": "ec2-user"}, "rocky9": {"user": "rocky"}, + "almalinux8": {"user": "ec2-user"}, } OS_TO_IMAGE_NAME_PART_MAP = { @@ -85,9 +96,10 @@ "rocky8": "rocky8-hvm", "rhel9": "rhel9-hvm", "rocky9": "rocky9-hvm", + "almalinux8": "almalinux8-hvm", } # We do not publicly publish/release Parallelcluster AMI of below OSSes -PRIVATE_OSES = ["rocky8", "rocky9"] +PRIVATE_OSES = ["rocky8", "rocky9", "almalinux8"] IMAGE_NAME_PART_TO_OS_MAP = {value: key for key, value in OS_TO_IMAGE_NAME_PART_MAP.items()} diff --git a/cli/src/pcluster/resources/imagebuilder/parallelcluster.yaml b/cli/src/pcluster/resources/imagebuilder/parallelcluster.yaml index f8d1176675..b3c23fca2e 100644 --- a/cli/src/pcluster/resources/imagebuilder/parallelcluster.yaml +++ b/cli/src/pcluster/resources/imagebuilder/parallelcluster.yaml @@ -30,6 +30,7 @@ phases: rocky.8*) echo 'rocky8' ;; rhel.9*) echo 'rhel9' ;; rocky.9*) echo 'rocky9' ;; + almalinux.8*) echo 'almalinux8' ;; *) echo "Unsupported OS: $RELEASE" && exit {{ FailExitCode }} ;; esac @@ -55,14 +56,14 @@ phases: set -x # Get OS info . /etc/os-release - # Check input base AMI OS and get OS information, the output should be like amzn.2 | ubuntu.20.04 | ubuntu.22.04 | rhel.8.7 | rocky.8.8 + # Check input base AMI OS and get OS information, the output should be like amzn.2023 | ubuntu.22.04 | rhel.8.10 | rocky.8.10 | almalinux.8.10 RELEASE="${!ID}${!VERSION_ID:+.${!VERSION_ID}}" # Use OS name from previous step OS="{{ build.OperatingSystemName.outputs.stdout }}" # Set platform - [[ $OS =~ ^(alinux|rhel|rocky) ]] && PLATFORM='RHEL' || PLATFORM='DEBIAN' + [[ $OS =~ ^(alinux|almalinux|rhel|rocky) ]] && PLATFORM='RHEL' || PLATFORM='DEBIAN' # Set URLs COOKBOOK_NAME="aws-parallelcluster-cookbook-${CfnParamCookbookVersion}" @@ -139,6 +140,7 @@ phases: yum versionlock ${!KERNEL_PACKAGES_PREFIX} ${!KERNEL_PACKAGES_PREFIX}-core ${!KERNEL_PACKAGES_PREFIX}-modules ${!KERNEL_PACKAGES_PREFIX}-modules-extra [[ $OS =~ rocky ]] && yum versionlock rocky-release rocky-repos [[ $OS =~ rhel ]] && yum versionlock redhat-release + [[ $OS == almalinux8 ]] && yum versionlock almalinux-release almalinux-repos else apt-get -y install linux-headers-$(uname -r) linux-modules-extra-$(uname -r) apt-mark hold linux-aws linux-base linux-headers-aws linux-image-aws linux-modules-extra-aws @@ -276,6 +278,7 @@ phases: yum versionlock delete ${!KERNEL_PACKAGES_PREFIX} ${!KERNEL_PACKAGES_PREFIX}-core ${!KERNEL_PACKAGES_PREFIX}-modules ${!KERNEL_PACKAGES_PREFIX}-modules-extra [[ $OS =~ rocky ]] && yum versionlock delete rocky-release rocky-repos [[ $OS =~ rhel ]] && yum versionlock delete redhat-release + [[ $OS == almalinux8 ]] && yum versionlock delete almalinux-release almalinux-repos else apt-mark unhold linux-aws linux-base linux-headers-aws linux-image-aws linux-modules-extra-aws fi diff --git a/cli/src/pcluster/resources/imagebuilder/parallelcluster_tag.yaml b/cli/src/pcluster/resources/imagebuilder/parallelcluster_tag.yaml index 3aa0e24c4c..55edad55d4 100644 --- a/cli/src/pcluster/resources/imagebuilder/parallelcluster_tag.yaml +++ b/cli/src/pcluster/resources/imagebuilder/parallelcluster_tag.yaml @@ -59,6 +59,8 @@ phases: OS='rhel9' elif [ $(echo "${RELEASE}" | grep '^rocky\.9') ]; then OS='rocky9' + elif [ $(echo "${RELEASE}" | grep '^almalinux\.8') ]; then + OS='almalinux8' fi echo ${OS} @@ -74,7 +76,7 @@ phases: which aws if [[ $? -ne 0 ]]; then echo "Installing unzip" - if [[ "{{ test.OperatingSystemName.outputs.stdout }}" =~ ^(alinux|rhel|rocky) ]]; then + if [[ "{{ test.OperatingSystemName.outputs.stdout }}" =~ ^(alinux|almalinux|rhel|rocky) ]]; then yum -y install unzip elif [[ "{{ test.OperatingSystemName.outputs.stdout }}" =~ ^ubuntu ]]; then apt-get -y install unzip diff --git a/cli/src/pcluster/resources/imagebuilder/parallelcluster_test.yaml b/cli/src/pcluster/resources/imagebuilder/parallelcluster_test.yaml index 3943883a2a..c9ea0183ab 100644 --- a/cli/src/pcluster/resources/imagebuilder/parallelcluster_test.yaml +++ b/cli/src/pcluster/resources/imagebuilder/parallelcluster_test.yaml @@ -39,6 +39,7 @@ phases: rocky.8*) echo rocky8;; rhel.9*) echo rhel9;; rocky.9*) echo rocky9;; + almalinux.8*) echo almalinux8;; *) echo "Operating System '${RELEASE}' is not supported. Failing build." && exit 1;; esac @@ -62,7 +63,7 @@ phases: - | set -v case '{{ test.OSName.outputs.stdout }}' in - alinux*|centos*|rhel*|rocky*) echo RHEL;; + alinux*|almalinux*|centos*|rhel*|rocky*) echo RHEL;; ubuntu*) echo DEBIAN;; esac @@ -90,7 +91,7 @@ phases: set -v ARCHITECTURE='{{ test.OSArchitecture.outputs.stdout }}' OS='{{ test.OSName.outputs.stdout }}' - if [ ${ARCHITECTURE} == 'arm64' ] && [[ ${OS} =~ ^(ubuntu(20|22)04|alinux(2|2023)|rhel8|rocky8|rhel9|rocky9)$ ]] || [ ${ARCHITECTURE} == 'x86_64' ]; then + if [ ${ARCHITECTURE} == 'arm64' ] && [[ ${OS} =~ ^(ubuntu(20|22)04|alinux(2|2023)|rhel8|rocky8|rhel9|rocky9|almalinux8)$ ]] || [ ${ARCHITECTURE} == 'x86_64' ]; then echo "true" else echo "false" @@ -393,4 +394,4 @@ phases: cd /etc/chef/cookbooks/{{ loop.value }} inspec exec test --profiles-path . --controls /tag:install/ /tag:testami/ --no-distinct-exit [[ $? -ne 0 ]] && echo "InSpec tests failed: {{ loop.value }}" && exit 1 - echo "InSpec tests passed: {{ loop.value }}" \ No newline at end of file + echo "InSpec tests passed: {{ loop.value }}" diff --git a/cli/src/pcluster/resources/imagebuilder/update_and_reboot.yaml b/cli/src/pcluster/resources/imagebuilder/update_and_reboot.yaml index 99043a0bdc..86e4307b48 100644 --- a/cli/src/pcluster/resources/imagebuilder/update_and_reboot.yaml +++ b/cli/src/pcluster/resources/imagebuilder/update_and_reboot.yaml @@ -10,7 +10,7 @@ constants: phases: - name: build steps: - # Check input base AMI OS and get OS information, the output should be like amzn.2 | ubuntu.20.04 | ubuntu.22.04 | rhel.8.7 | rocky.8.8 + # Check input base AMI OS and get OS information, the output should be like amzn.2023 | ubuntu.22.04 | rhel.8.10 | rocky.8.10 | almalinux.8.10 - name: OperatingSystemRelease action: ExecuteBash inputs: @@ -49,6 +49,8 @@ phases: OS='rhel9' elif [ `echo "${!RELEASE}" | grep '^rocky\.9'` ]; then OS='rocky9' + elif [ `echo "${!RELEASE}" | grep '^almalinux\.8'` ]; then + OS='almalinux8' else echo "Operating System '${!RELEASE}' is not supported. Failing build." exit {{ FailExitCode }} @@ -65,7 +67,7 @@ phases: set -x OS='{{ build.OperatingSystemName.outputs.stdout }}' - if [ `echo "${!OS}" | grep -E '^(alinux|rhel|rocky)'` ]; then + if [ `echo "${!OS}" | grep -E '^(alinux|almalinux|rhel|rocky)'` ]; then PLATFORM='RHEL' elif [ `echo "${!OS}" | grep -E '^ubuntu'` ]; then PLATFORM='DEBIAN' @@ -81,15 +83,15 @@ phases: - | set -x RELEASE='{{ build.OperatingSystemRelease.outputs.stdout }}' - if [ `echo "${!RELEASE}" | grep -Ev '^(amzn|ubuntu|rhel|rocky)'` ]; then + if [ `echo "${!RELEASE}" | grep -Ev '^(amzn|ubuntu|rhel|rocky|almalinux)'` ]; then echo "This component does not support '${!RELEASE}'. Failing build." exit {{ FailExitCode }} fi - # This component only supports aarch64 CPUs on Amazon Linux 2, Ubuntu2204, RHEL8, Rocky8, RHEL9 and Rocky9 + # This component supports aarch64 CPUs on Amazon Linux 2023, Ubuntu, RHEL, Rocky Linux, and AlmaLinux 8 ARCH=$(uname -m) if [[ `echo ${!ARCH}` == 'aarch64' ]]; then - if [ `echo "${!RELEASE}" | grep -Ev '^(amzn\.2|ubuntu\.20\.04|ubuntu\.22\.04|ubuntu\.24\.04|rhel\.8|rocky\.8|rhel\.9|rocky\.9)'` ]; then + if [ `echo "${!RELEASE}" | grep -Ev '^(amzn\.2023|ubuntu\.22\.04|ubuntu\.24\.04|rhel\.8|rocky\.8|rhel\.9|rocky\.9|almalinux\.8)'` ]; then echo "This component does not support '${!RELEASE}' on ARM64 CPUs. Failing build." exit {{ FailExitCode }} fi @@ -179,6 +181,8 @@ phases: yum versionlock rocky-release rocky-repos elif [[ ${!OS} == "rhel8" ]] || [[ ${!OS} == "rhel9" ]] ; then yum versionlock redhat-release + elif [[ ${!OS} == "almalinux8" ]] ; then + yum versionlock almalinux-release almalinux-repos fi echo "Kernel version locked" fi @@ -197,7 +201,7 @@ phases: if [[ ${!PLATFORM} == RHEL ]]; then yum -y update - if [[ ${!OS} == "rhel8" ]] || [[ ${!OS} == "rocky8" ]] || [[ ${!OS} == "rhel9" ]] || [[ ${!OS} == "rocky9" ]] || [[ ${!OS} == "alinux2023" ]] ; then + if [[ ${!OS} == "rhel8" ]] || [[ ${!OS} == "rocky8" ]] || [[ ${!OS} == "rhel9" ]] || [[ ${!OS} == "rocky9" ]] || [[ ${!OS} == "almalinux8" ]] || [[ ${!OS} == "alinux2023" ]] ; then # package-cleanup has changed in RHEL8 and it works differently https://access.redhat.com/solutions/1227 yum remove -y $(yum repoquery --installonly --latest-limit=-2 -q) else @@ -243,6 +247,8 @@ phases: yum versionlock delete rocky-release elif [[ ${!OS} == "rhel8" ]] || [[ ${!OS} == "rhel9" ]] ; then yum versionlock delete redhat-release + elif [[ ${!OS} == "almalinux8" ]] ; then + yum versionlock delete almalinux-release almalinux-repos fi echo "Kernel version unlocked" fi diff --git a/cli/src/pcluster/templates/cw_dashboard_builder.py b/cli/src/pcluster/templates/cw_dashboard_builder.py index 15b2d96cec..a8f735ad6c 100644 --- a/cli/src/pcluster/templates/cw_dashboard_builder.py +++ b/cli/src/pcluster/templates/cw_dashboard_builder.py @@ -746,7 +746,9 @@ def _add_cw_log(self): [ self._new_cw_log_widget( title="system-messages", - conditions=[Condition(["alinux2023", "rhel8", "rocky8", "rhel9", "rocky9"], base_os)], + conditions=[ + Condition(["alinux2023", "rhel8", "rocky8", "rhel9", "rocky9", "almalinux8"], base_os) + ], filters=[self._new_filter(pattern=f"{head_private_ip}.*system-messages")], ), self._new_cw_log_widget( diff --git a/cli/src/pcluster/validators/cluster_validators.py b/cli/src/pcluster/validators/cluster_validators.py index 5b0f02208a..17e0365dda 100644 --- a/cli/src/pcluster/validators/cluster_validators.py +++ b/cli/src/pcluster/validators/cluster_validators.py @@ -51,7 +51,10 @@ SHARED_STORAGE_NAME_MAX_LENGTH = 30 NAME_REGEX = r"^[a-z][a-z0-9\-]*$" -EFA_UNSUPPORTED_ARCHITECTURES_OSES = {"x86_64": [], "arm64": []} +EFA_UNSUPPORTED_ARCHITECTURES_OSES = { + "x86_64": ["almalinux8"], + "arm64": ["almalinux8"], +} EFS_MESSAGES = { "errors": { diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_disabled_efa_no_placement_group/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_disabled_efa_no_placement_group/output.txt index d4844de83c..39e7e0e28b 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_disabled_efa_no_placement_group/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_disabled_efa_no_placement_group/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 The EC2 instance selected supports enhanced networking capabilities using Elastic Fabric Adapter (EFA). EFA enables you to run applications requiring high levels of inter-node communications at scale on AWS at no additional charge (https://docs.aws.amazon.com/parallelcluster/latest/ug/efa-v3.html). Allowed values for VPC ID: # id name number_of_subnets diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_efa_not_supported/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_efa_not_supported/output.txt index 7ab41c149d..da4edd0285 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_efa_not_supported/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_efa_not_supported/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_default_placement_group/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_default_placement_group/output.txt index b3c7ebdf45..8ec5c13fb6 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_default_placement_group/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_default_placement_group/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 The EC2 instance selected supports enhanced networking capabilities using Elastic Fabric Adapter (EFA). EFA enables you to run applications requiring high levels of inter-node communications at scale on AWS at no additional charge (https://docs.aws.amazon.com/parallelcluster/latest/ug/efa-v3.html). Enabling EFA requires compute instances to be placed within a Placement Group. Please specify an existing Placement Group name or leave it blank for ParallelCluster to create one. Allowed values for VPC ID: diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_existing_placement_group/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_existing_placement_group/output.txt index b3c7ebdf45..8ec5c13fb6 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_existing_placement_group/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_existing_placement_group/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 The EC2 instance selected supports enhanced networking capabilities using Elastic Fabric Adapter (EFA). EFA enables you to run applications requiring high levels of inter-node communications at scale on AWS at no additional charge (https://docs.aws.amazon.com/parallelcluster/latest/ug/efa-v3.html). Enabling EFA requires compute instances to be placed within a Placement Group. Please specify an existing Placement Group name or leave it blank for ParallelCluster to create one. Allowed values for VPC ID: diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_non_existent_placement_group/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_non_existent_placement_group/output.txt index e348943a3a..be30212e41 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_non_existent_placement_group/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_enabled_efa_non_existent_placement_group/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 The EC2 instance selected supports enhanced networking capabilities using Elastic Fabric Adapter (EFA). EFA enables you to run applications requiring high levels of inter-node communications at scale on AWS at no additional charge (https://docs.aws.amazon.com/parallelcluster/latest/ug/efa-v3.html). Enabling EFA requires compute instances to be placed within a Placement Group. Please specify an existing Placement Group name or leave it blank for ParallelCluster to create one. ERROR: non-existent-test-pg is not an acceptable value for Placement Group name diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_filtered_subnets_by_az/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_filtered_subnets_by_az/output.txt index fd3008ee81..7aa12b3498 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_filtered_subnets_by_az/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_filtered_subnets_by_az/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_automation_no_errors/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_automation_no_errors/output.txt index 7ab41c149d..da4edd0285 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_automation_no_errors/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_automation_no_errors/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_input_no_automation_no_errors/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_input_no_automation_no_errors/output.txt index 0a03c12c58..27180987ae 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_input_no_automation_no_errors/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_no_input_no_automation_no_errors/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors/output.txt index 5008a35ee0..47f91f29f8 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors_empty_vpc/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors_empty_vpc/output.txt index 0df83774f0..3f3e5c56db 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors_empty_vpc/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_subnet_automation_no_errors_empty_vpc/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_errors/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_errors/output.txt index 2da76c78ac..80165f0b83 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_errors/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_errors/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for Availability Zone: 1. eu-west-1a 2. eu-west-1b diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region/output.txt index 7ec880fb67..f8dcbc3071 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 There are no VPC for the given region. Starting automatic creation of VPC and subnets... Allowed values for Availability Zone: 1. eu-west-1a diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region_public/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region_public/output.txt index 7ec880fb67..f8dcbc3071 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region_public/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_vpc_automation_no_vpc_in_region_public/output.txt @@ -36,6 +36,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 There are no VPC for the given region. Starting automatic creation of VPC and subnets... Allowed values for Availability Zone: 1. eu-west-1a diff --git a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_with_region_arg/output.txt b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_with_region_arg/output.txt index 0b7879b0dc..1a3490507e 100644 --- a/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_with_region_arg/output.txt +++ b/cli/tests/pcluster/cli/configure/test_pcluster_configure/test_with_region_arg/output.txt @@ -19,6 +19,7 @@ Allowed values for Operating System: 5. rocky8 6. rhel9 7. rocky9 +8. almalinux8 Allowed values for VPC ID: # id name number_of_subnets --- ------------ --------------------------------- ------------------- diff --git a/cli/tests/pcluster/schemas/test_cluster_schema.py b/cli/tests/pcluster/schemas/test_cluster_schema.py index 3f179af290..3ee88de03a 100644 --- a/cli/tests/pcluster/schemas/test_cluster_schema.py +++ b/cli/tests/pcluster/schemas/test_cluster_schema.py @@ -69,6 +69,7 @@ def test_cluster_schema_slurm(mocker, test_datadir, config_file_name): (None, None, "Missing data for required field"), ("ubuntu2204", "ami-12345678", None), ("alinux2023", None, None), + ("almalinux8", "ami-12345678", None), ], ) def test_image_schema(os, custom_ami, failure_message): @@ -85,6 +86,9 @@ def test_image_schema(os, custom_ami, failure_message): image = ImageSchema().load(image_schema) assert_that(image.os).is_equal_to(os) assert_that(image.custom_ami).is_equal_to(custom_ami) + output_schema = ImageSchema() + output_schema.context = {"delete_defaults_when_dump": True} + assert_that(output_schema.dump(image)).is_equal_to(image_schema) @pytest.mark.parametrize( diff --git a/cli/tests/pcluster/test_almalinux8_support.py b/cli/tests/pcluster/test_almalinux8_support.py new file mode 100644 index 0000000000..a31af2981d --- /dev/null +++ b/cli/tests/pcluster/test_almalinux8_support.py @@ -0,0 +1,71 @@ +# Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance +# with the License. A copy of the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "LICENSE.txt" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +# and limitations under the License. + +from pathlib import Path + +import pytest +import yaml +from assertpy import assert_that + +from pcluster.constants import ( + CAPACITY_RESERVATION_OS_MAP, + CR_PLATFORM_LINUX_UNIX, + OS_MAPPING, + OS_TO_IMAGE_NAME_PART_MAP, + PRIVATE_OSES, + SUPPORTED_OSES, +) + + +IMAGEBUILDER_RESOURCES = ( + Path(__file__).resolve().parents[2] / "src" / "pcluster" / "resources" / "imagebuilder" +) + + +def _component_commands(component_name): + component = yaml.safe_load((IMAGEBUILDER_RESOURCES / component_name).read_text(encoding="utf-8")) + commands = [] + for phase in component["phases"]: + for step in phase["steps"]: + inputs = step.get("inputs", {}) + if isinstance(inputs, dict): + commands.extend(inputs.get("commands", [])) + return "\n".join(commands) + + +def test_almalinux8_configuration_contract(): + assert_that(SUPPORTED_OSES).contains("almalinux8") + assert_that(PRIVATE_OSES).contains("almalinux8") + assert_that(OS_MAPPING["almalinux8"]).is_equal_to({"user": "ec2-user"}) + assert_that(CAPACITY_RESERVATION_OS_MAP["almalinux8"]).is_equal_to(CR_PLATFORM_LINUX_UNIX) + assert_that(OS_TO_IMAGE_NAME_PART_MAP["almalinux8"]).is_equal_to("almalinux8-hvm") + + +@pytest.mark.parametrize( + "component_name", + [ + "parallelcluster.yaml", + "parallelcluster_tag.yaml", + "parallelcluster_test.yaml", + "update_and_reboot.yaml", + ], +) +def test_imagebuilder_components_detect_almalinux8(component_name): + commands = _component_commands(component_name) + assert_that(commands).contains("almalinux") + assert_that(commands).contains("almalinux8") + + +@pytest.mark.parametrize("component_name", ["parallelcluster.yaml", "update_and_reboot.yaml"]) +def test_imagebuilder_components_preserve_almalinux_release_packages_during_kernel_lock(component_name): + commands = _component_commands(component_name) + assert_that(commands).contains("yum versionlock almalinux-release almalinux-repos") + assert_that(commands).contains("yum versionlock delete almalinux-release almalinux-repos") diff --git a/cli/tests/pcluster/test_utils.py b/cli/tests/pcluster/test_utils.py index 4dfd98be2b..148ca05510 100644 --- a/cli/tests/pcluster/test_utils.py +++ b/cli/tests/pcluster/test_utils.py @@ -88,11 +88,29 @@ def test_generate_random_prefix(): [ ( "x86_64", - ["alinux2023", "ubuntu2204", "ubuntu2404", "rhel8", "rocky8", "rhel9", "rocky9"], + [ + "alinux2023", + "ubuntu2204", + "ubuntu2404", + "rhel8", + "rocky8", + "rhel9", + "rocky9", + "almalinux8", + ], ), ( "arm64", - ["alinux2023", "ubuntu2204", "ubuntu2404", "rhel8", "rocky8", "rhel9", "rocky9"], + [ + "alinux2023", + "ubuntu2204", + "ubuntu2404", + "rhel8", + "rocky8", + "rhel9", + "rocky9", + "almalinux8", + ], ), ], ) diff --git a/cli/tests/pcluster/validators/test_cluster_validators.py b/cli/tests/pcluster/validators/test_cluster_validators.py index 60d881bb86..10dbb6e5aa 100644 --- a/cli/tests/pcluster/validators/test_cluster_validators.py +++ b/cli/tests/pcluster/validators/test_cluster_validators.py @@ -958,6 +958,19 @@ def _append_mocked_describe_sg_request(ip_perm, ip_perm_egress, sec_group): (True, "rocky9", "arm64", None), (True, "rhel8", "x86_64", None), (True, "rhel8", "arm64", None), + ( + True, + "almalinux8", + "x86_64", + "EFA is currently not supported on almalinux8 for x86_64 architecture.", + ), + ( + True, + "almalinux8", + "arm64", + "EFA is currently not supported on almalinux8 for arm64 architecture.", + ), + (False, "almalinux8", "x86_64", None), ], ) def test_efa_os_architecture_validator(efa_enabled, os, architecture, expected_message): @@ -3777,6 +3790,7 @@ def test_multi_network_interfaces_instances_validator_mixed_queue(aws_api_mock): ("ami-000000000000", "rocky8", None, None), ("ami-000000000000", "alinux2023", None, None), ("ami-000000000000", "rhel8", None, None), + ("ami-000000000000", "almalinux8", None, None), ("ami-000000000000", "ubuntu2204", None, None), ("ami-000000000000", "ubuntu2404", None, None), ( @@ -3788,6 +3802,15 @@ def test_multi_network_interfaces_instances_validator_mixed_queue(aws_api_mock): "https://docs.aws.amazon.com/parallelcluster/latest/ug/building-custom-ami-v3.html", FailureLevel.ERROR, ), + ( + None, + "almalinux8", + "ParallelCluster has no official AMI for almalinux8. " + "Please build your own AMI using pcluster build-image command, " + "as explained in the documentation: " + "https://docs.aws.amazon.com/parallelcluster/latest/ug/building-custom-ami-v3.html", + FailureLevel.ERROR, + ), (None, "alinux2023", None, None), (None, "rhel8", None, None), (None, "ubuntu2204", None, None), diff --git a/tests/integration-tests/configs/common.jinja2 b/tests/integration-tests/configs/common.jinja2 index 47ad4aad36..867f243ef6 100644 --- a/tests/integration-tests/configs/common.jinja2 +++ b/tests/integration-tests/configs/common.jinja2 @@ -14,7 +14,7 @@ {%- set INSTANCES_DEFAULT = ["c5.xlarge", "m6g.xlarge"] -%} {%- set INSTANCES_EFA_SUPPORTED_X86 = ["c5n.9xlarge"] -%} {%- set INSTANCES_EFA_UNSUPPORTED_X86 = ["t3.micro"] -%} -{%- set NOT_RELEASED_OSES = ["rocky8", "rocky9"] -%} +{%- set NOT_RELEASED_OSES = ["rocky8", "rocky9", "almalinux8"] -%} {%- macro instance(instance_key) -%} {%- if additional_instance_types_map -%} diff --git a/tests/integration-tests/configs/develop.yaml b/tests/integration-tests/configs/develop.yaml index 8b28132f83..f4b44d63ea 100644 --- a/tests/integration-tests/configs/develop.yaml +++ b/tests/integration-tests/configs/develop.yaml @@ -1,6 +1,8 @@ {%- import 'common.jinja2' as common with context -%} {{- common.OSS_COMMERCIAL_X86.append("rocky8") or "" -}} {{- common.OSS_COMMERCIAL_X86.append("rocky9") or "" -}} +{{- common.OSS_COMMERCIAL_X86.append("almalinux8") or "" -}} +{{- common.OSS_COMMERCIAL_ARM.append("almalinux8") or "" -}} --- test-suites: ad_integration: diff --git a/tests/integration-tests/tests/common/osu_common.py b/tests/integration-tests/tests/common/osu_common.py index f982f7c815..9a228ed015 100644 --- a/tests/integration-tests/tests/common/osu_common.py +++ b/tests/integration-tests/tests/common/osu_common.py @@ -20,7 +20,7 @@ OSU_COMMON_DATADIR = pathlib.Path(__file__).parent / "data/osu/" SUPPORTED_MPIS = ["openmpi", "intelmpi"] -PRIVATE_OSES = ["rocky8", "rocky9"] +PRIVATE_OSES = ["rocky8", "rocky9", "almalinux8"] def compile_osu(mpi_variant, remote_command_executor): diff --git a/tests/integration-tests/tests/common/utils.py b/tests/integration-tests/tests/common/utils.py index 7bda9f3dbd..e71e57be47 100644 --- a/tests/integration-tests/tests/common/utils.py +++ b/tests/integration-tests/tests/common/utils.py @@ -47,6 +47,7 @@ GPU_JOB_SCRIPT = pathlib.Path(__file__).parent / "data/gpu_job.sh" RHEL_OWNERS = ["309956199498", "841258680906", "219670896067"] +ALMALINUX_OWNERS = ["764336703387"] OS_TO_OFFICIAL_AMI_NAME_OWNER_MAP = { "alinux2023": {"name": "al2023-ami-2023.*.*.*-kernel-6.1-*", "owners": ["amazon"]}, @@ -73,6 +74,10 @@ "rocky8.9": {"name": "Rocky-8-EC2-Base-8.9*", "owners": ["792107900819"]}, # TODO add china and govcloud accounts "rhel9": {"name": "RHEL-9.*_HVM*", "owners": RHEL_OWNERS}, "rocky9": {"name": "Rocky-9-EC2-Base-9.*", "owners": ["792107900819"]}, # TODO add china and govcloud accounts + "almalinux8": { + "name": {"x86_64": "AlmaLinux OS 8*x86_64", "arm64": "AlmaLinux OS 8*aarch64"}, + "owners": ALMALINUX_OWNERS, + }, } # Remarkable AMIs are latest deep learning base AMI and FPGA developer AMI without pcluster infrastructure @@ -120,6 +125,7 @@ "rocky8": {"name": "rocky8-hvm-*-*", "owners": PCLUSTER_AMI_OWNERS}, "rhel9": {"name": "rhel9-hvm-*-*", "owners": PCLUSTER_AMI_OWNERS}, "rocky9": {"name": "rocky9-hvm-*-*", "owners": PCLUSTER_AMI_OWNERS}, + "almalinux8": {"name": "almalinux8-hvm-*-*", "owners": PCLUSTER_AMI_OWNERS}, } FIRST_STAGE_AMI_OWNERS = ["self", "447714826191"] diff --git a/tests/integration-tests/utils.py b/tests/integration-tests/utils.py index a4e468b292..589f2bbd8e 100644 --- a/tests/integration-tests/utils.py +++ b/tests/integration-tests/utils.py @@ -575,6 +575,7 @@ def get_username_for_os(os): "rocky8": "rocky", "rhel9": "ec2-user", "rocky9": "rocky", + "almalinux8": "ec2-user", } return usernames.get(os)