Skip to content

[Build Image] Add user-data.sh for Parallelcluster build image #6771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions cli/src/pcluster/config/imagebuilder_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,17 @@ def __init__(
self.enabled = enabled


class DisableKernelUpdate(Resource):
"""Represent the DisableKernelUpdate configuration for the ImageBuilder."""

def __init__(
self,
enabled: bool = None,
):
super().__init__()
self.enabled = Resource.init_param(enabled, default=True)


class LustreClient(Resource):
"""Represent the LustreClient configuration for the ImageBuilder."""

Expand Down Expand Up @@ -192,6 +203,7 @@ def __init__(
security_group_ids: List[str] = None,
components: List[Component] = None,
update_os_packages: UpdateOsPackages = None,
disable_kernel_update: DisableKernelUpdate = None,
imds: Imds = None,
installation: Installation = None,
):
Expand All @@ -204,6 +216,7 @@ def __init__(
self.security_group_ids = security_group_ids
self.components = components
self.update_os_packages = update_os_packages
self.disable_kernel_update = disable_kernel_update or DisableKernelUpdate()
self.imds = imds or Imds(implied="v2.0")
self.installation = installation or Installation()

Expand Down Expand Up @@ -241,7 +254,6 @@ def __init__(
terminate_instance_on_failure: bool = None,
disable_validate_and_test: bool = None,
cinc_installer_url: str = None,
disable_kernel_update: bool = None,
slurm_patches_s3_archive: str = None,
**kwargs
):
Expand All @@ -251,7 +263,6 @@ def __init__(
self.terminate_instance_on_failure = Resource.init_param(terminate_instance_on_failure, default=True)
self.disable_validate_and_test = Resource.init_param(disable_validate_and_test, default=True)
self.cinc_installer_url = Resource.init_param(cinc_installer_url, default="")
self.disable_kernel_update = Resource.init_param(disable_kernel_update, default=False)
self.slurm_patches_s3_archive = Resource.init_param(slurm_patches_s3_archive, default="")


Expand Down Expand Up @@ -334,7 +345,6 @@ def __init__(self, config: ImageBuilderConfig):
self.custom_node_package = None
self.custom_awsbatchcli_package = None
self.base_os = None
self.disable_kernel_update = None
self.slurm_patches_s3_archive = None
self._set_default(config)

Expand All @@ -352,7 +362,9 @@ def _set_default(self, config: ImageBuilderConfig):
dev_settings.slurm_patches_s3_archive if dev_settings and dev_settings.slurm_patches_s3_archive else ""
)
self.base_os = "{{ build.OperatingSystemName.outputs.stdout }}"
self.disable_kernel_update = "true" if dev_settings and dev_settings.disable_kernel_update else "false"
self.disable_kernel_update = (
{"enabled": "yes"} if config.build.disable_kernel_update.enabled else {"enabled": "no"}
)
for key, value in self.__dict__.items():
if not key.startswith("_") and key not in self._cluster_attributes:
self._cluster_attributes.update({key: value})
94 changes: 78 additions & 16 deletions cli/src/pcluster/resources/imagebuilder/parallelcluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ phases:
set -v
OS='{{ build.OperatingSystemName.outputs.stdout }}'

if [ `echo "${!OS}" | grep -E '^(alinux|centos|rhel|rocky)'` ]; then
if [ `echo "${!OS}" | grep -E '^(alinux|rhel|rocky)'` ]; then
PLATFORM='RHEL'
elif [ `echo "${!OS}" | grep -E '^ubuntu'` ]; then
PLATFORM='DEBIAN'
Expand Down Expand Up @@ -167,7 +167,7 @@ phases:
set -v
if [ ${CfnParamUpdateOsAndReboot} == false ]; then
RELEASE='{{ build.OperatingSystemRelease.outputs.stdout }}'
if [ `echo "${!RELEASE}" | grep -Ev '^(amzn|centos|ubuntu|rhel|rocky)'` ]; then
if [ `echo "${!RELEASE}" | grep -Ev '^(amzn|ubuntu|rhel|rocky)'` ]; then
echo "This component does not support '${!RELEASE}'. Failing build."
exit {{ FailExitCode }}
fi
Expand All @@ -182,6 +182,54 @@ phases:
fi
fi

- name: CreatingJsonFile
action: CreateFile
inputs:
- path: /etc/parallelcluster/image_dna.json
content: |
${CfnParamChefDnaJson}
overwrite: true

- name: DisableKernelUpdate
action: ExecuteBash
inputs:
commands:
- |
set -v
DISABLE_KERNEL_UPDATE=$(cat /etc/parallelcluster/image_dna.json | jq -r '.cluster.disable_kernel_update.enabled')
echo "${!DISABLE_KERNEL_UPDATE}"

- name: PinKernelVersion
action: ExecuteBash
inputs:
commands:
- |
set -v
OS='{{ build.OperatingSystemName.outputs.stdout }}'
PLATFORM='{{ build.PlatformName.outputs.stdout }}'
DISABLE_KERNEL_UPDATE='{{ build.DisableKernelUpdate.outputs.stdout }}'

if [[ ${!DISABLE_KERNEL_UPDATE} == true ]]; then
if [[ ${!PLATFORM} == RHEL ]]; then
yum install -y yum-plugin-versionlock
# listing all the packages because wildcard does not work as expected
yum versionlock kernel kernel-core kernel-modules

if [[ ${!OS} == "alinux2" ]] || [[ ${!OS} == "alinux2023" ]] ; then
yum versionlock kernel-abi-whitelists
else
yum versionlock kernel-abi-stablelists
fi

if [[ ${!OS} == "rocky8" ]] || [[ ${!OS} == "rocky9" ]] ; then
yum versionlock rocky-release rocky-repos
elif [[ ${!OS} == "rhel8" ]] || [[ ${!OS} == "rhel9" ]] ; then
yum versionlock redhat-release
fi
echo "Kernel version locked"
fi
fi

# Install prerequisite OS packages
- name: InstallPrerequisite
action: ExecuteBash
Expand All @@ -203,12 +251,6 @@ phases:
fi
yum -y update krb5-libs
yum -y groupinstall development && sudo yum -y install curl wget jq


if [[ ${!OS} =~ ^centos ]]; then
/bin/sed -r -i -e 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
grub2-mkconfig -o /boot/grub2/grub.cfg
fi
elif [[ ${!PLATFORM} == DEBIAN ]]; then
if [[ "${CfnParamUpdateOsAndReboot}" == "false" ]]; then
# disable apt-daily.timer to avoid dpkg lock
Expand Down Expand Up @@ -282,14 +324,6 @@ phases:
cookbook_path ['/etc/chef/cookbooks']
overwrite: true

- name: CreatingJsonFile
action: CreateFile
inputs:
- path: /etc/parallelcluster/image_dna.json
content: |
${CfnParamChefDnaJson}
overwrite: true

- name: InstallPClusterPackages
action: ExecuteBash
inputs:
Expand All @@ -308,6 +342,34 @@ phases:
{{ build.PClusterCookbookVersionName.outputs.stdout }}
overwrite: true

- name: RemoveKernelPin
action: ExecuteBash
inputs:
commands:
- |
set -v
OS='{{ build.OperatingSystemName.outputs.stdout }}'
PLATFORM='{{ build.PlatformName.outputs.stdout }}'
DISABLE_KERNEL_UPDATE='{{ build.DisableKernelUpdate.outputs.stdout }}'

# Remove kernel version lock
if [[ ${!DISABLE_KERNEL_UPDATE} == true ]] && [[ ${!PLATFORM} == RHEL ]]; then
yum versionlock delete kernel kernel-core kernel-modules

if [[ ${!OS} == "alinux2" ]] || [[ ${!OS} == "alinux2023" ]] ; then
yum versionlock delete kernel-abi-whitelists
else
yum versionlock delete kernel-abi-stablelists
fi

if [[ ${!OS} == "rocky8" ]] || [[ ${!OS} == "rocky9" ]] ; then
yum versionlock delete rocky-release
elif [[ ${!OS} == "rhel8" ]] || [[ ${!OS} == "rhel9" ]] ; then
yum versionlock delete redhat-release
fi
echo "Kernel version unlocked"
fi

- name: KeepSSM
action: ExecuteBash
inputs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ phases:
set -v
OS='{{ validate.OperatingSystemName.outputs.stdout }}'

if [ `echo "${OS}" | grep -E '^(alinux|centos|rhel|rocky)'` ]; then
if [ `echo "${OS}" | grep -E '^(alinux|rhel|rocky)'` ]; then
PLATFORM='RHEL'
elif [ `echo "${OS}" | grep -E '^ubuntu'` ]; then
PLATFORM='DEBIAN'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ phases:
set -v
OS='{{ build.OperatingSystemName.outputs.stdout }}'

if [ `echo "${!OS}" | grep -E '^(alinux|centos|rhel|rocky)'` ]; then
if [ `echo "${!OS}" | grep -E '^(alinux|rhel|rocky)'` ]; then
PLATFORM='RHEL'
elif [ `echo "${!OS}" | grep -E '^ubuntu'` ]; then
PLATFORM='DEBIAN'
Expand All @@ -83,7 +83,7 @@ phases:
- |
set -v
RELEASE='{{ build.OperatingSystemRelease.outputs.stdout }}'
if [ `echo "${!RELEASE}" | grep -Ev '^(amzn|centos|ubuntu|rhel|rocky)'` ]; then
if [ `echo "${!RELEASE}" | grep -Ev '^(amzn|ubuntu|rhel|rocky)'` ]; then
echo "This component does not support '${!RELEASE}'. Failing build."
exit {{ FailExitCode }}
fi
Expand Down Expand Up @@ -181,7 +181,7 @@ phases:
commands:
- |
set -v
DISABLE_KERNEL_UPDATE=$(cat /etc/parallelcluster/image_dna.json | jq -r '.cluster.disable_kernel_update')
DISABLE_KERNEL_UPDATE=$(cat /etc/parallelcluster/image_dna.json | jq -r '.cluster.disable_kernel_update.enabled')
echo "${!DISABLE_KERNEL_UPDATE}"

- name: PinKernelVersion
Expand Down
10 changes: 10 additions & 0 deletions cli/src/pcluster/resources/imagebuilder/user_data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0

--==BOUNDARY==
Content-Type: text/cloud-config; charset=us-ascii
MIME-Version: 1.0

package_update: false
package_upgrade: false
repo_upgrade: none
14 changes: 13 additions & 1 deletion cli/src/pcluster/schemas/imagebuilder_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pcluster.config.imagebuilder_config import (
Build,
Component,
DisableKernelUpdate,
DistributionConfiguration,
Iam,
Image,
Expand Down Expand Up @@ -170,6 +171,17 @@ def make_resource(self, data, **kwargs):
return UpdateOsPackages(**data)


class DisableKernelUpdateSchema(BaseSchema):
"""Represent the schema of the ImageBuilder DisableKernelUpdate."""

enabled = fields.Bool()

@post_load
def make_resource(self, data, **kwargs):
"""Generate resource."""
return DisableKernelUpdate(**data)


class LustreClientSchema(BaseSchema):
"""Represent the schema of the ImageBuilder NvidiaSoftware."""

Expand Down Expand Up @@ -215,6 +227,7 @@ class BuildSchema(BaseSchema):
security_group_ids = fields.List(fields.Str)
subnet_id = fields.Str(validate=get_field_validator("subnet_id"))
update_os_packages = fields.Nested(UpdateOsPackagesSchema)
disable_kernel_update = fields.Nested(DisableKernelUpdateSchema)
imds = fields.Nested(ImdsSchema)
installation = fields.Nested(InstallationSchema)

Expand Down Expand Up @@ -243,7 +256,6 @@ class ImagebuilderDevSettingsSchema(BaseDevSettingsSchema):
terminate_instance_on_failure = fields.Bool()
disable_validate_and_test = fields.Bool()
cinc_installer_url = fields.Str()
disable_kernel_update = fields.Bool()

@post_load
def make_resource(self, data, **kwargs):
Expand Down
23 changes: 23 additions & 0 deletions cli/src/pcluster/templates/imagebuilder_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,30 @@ def _add_imagebuilder_distribution_configuration(self, ami_tags, build_tags, lam

return distribution_configuration_resource

def _add_imagebuilder_user_data_override(self):

additional_instance_configuration_property = None
if (
self.config.build
and self.config.build.disable_kernel_update
and self.config.build.disable_kernel_update.enabled
):
imagebuilder_user_data = os.path.join(
imagebuilder_utils.get_resources_directory(), "imagebuilder", "user_data.sh"
)
with open(imagebuilder_user_data, "r", encoding="utf-8") as user_data_file:
user_data_content = user_data_file.read()

additional_instance_configuration_property = (
imagebuilder.CfnImageRecipe.AdditionalInstanceConfigurationProperty(
user_data_override=Fn.base64(user_data_content)
)
)
return additional_instance_configuration_property

def _add_imagebuilder_image_recipe(self, build_tags, components, lambda_cleanup_policy_statements):
# ImageBuilderImageRecipe

image_recipe_resource = imagebuilder.CfnImageRecipe(
self,
"ImageRecipe",
Expand All @@ -395,6 +417,7 @@ def _add_imagebuilder_image_recipe(self, build_tags, components, lambda_cleanup_
tags=build_tags,
parent_image=self.config.build.parent_image,
components=components,
additional_instance_configuration=self._add_imagebuilder_user_data_override(),
block_device_mappings=[
imagebuilder.CfnImageRecipe.InstanceBlockDeviceMappingProperty(
device_name=self._get_root_device_name(),
Expand Down
2 changes: 2 additions & 0 deletions cli/tests/pcluster/config/dummy_imagebuilder_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
AdditionalIamPolicy,
Build,
Component,
DisableKernelUpdate,
DistributionConfiguration,
Iam,
Image,
Expand Down Expand Up @@ -41,6 +42,7 @@
"iam": Iam,
"additional_iam_policies": AdditionalIamPolicy,
"update_os_packages": UpdateOsPackages,
"disable_kernel_update": DisableKernelUpdate,
"imds": Imds,
"installation": Installation,
"lustre_client": LustreClient,
Expand Down
Loading
Loading