Skip to content
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
52 changes: 52 additions & 0 deletions internal/kmmmodule/dockerfiles/DockerfileTemplate.sles
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
FROM $$BASEIMG_REGISTRY/suse/sle15:$$VERSION AS builder

ARG KERNEL_FULL_VERSION

ARG DRIVERS_VERSION

ARG REPO_URL

RUN zypper --non-interactive --gpg-auto-import-keys refresh

# Note: Only kernel-default-devel is needed (provides kernel headers)
# kernel-source package does NOT exist in SLES repositories
RUN zypper --non-interactive install -y \
kernel-default-devel \
gcc \
make \
bc \
bison \
flex \
libelf-devel \
perl \
python3 \
python3-setuptools \
python3-wheel

# Add AMD GPU repository for SLES
# The $$VERSION variable (e.g., "15.6", "15.7") is substituted at runtime
RUN zypper --non-interactive addrepo \
--no-gpgcheck \
${REPO_URL}/amdgpu/${DRIVERS_VERSION}/sle/$$VERSION/main/x86_64/ \
amdgpu

# Refresh repositories again to include AMD repo
RUN zypper --non-interactive --gpg-auto-import-keys refresh
RUN zypper --non-interactive --gpg-auto-import-keys install -y amdgpu-dkms
RUN depmod ${KERNEL_FULL_VERSION}


FROM $$BASEIMG_REGISTRY/suse/sle15:$$VERSION
ARG KERNEL_FULL_VERSION

RUN zypper --non-interactive --gpg-auto-import-keys refresh && \
zypper --non-interactive install -y kmod

RUN mkdir -p /opt/lib/modules/${KERNEL_FULL_VERSION}/updates/

# Note: amdgpu-dkms on SLES places modules in /lib/modules/.../updates/ (not updates/dkms/)
COPY --from=builder /lib/modules/${KERNEL_FULL_VERSION}/updates/amd* /opt/lib/modules/${KERNEL_FULL_VERSION}/updates/
COPY --from=builder /lib/modules/${KERNEL_FULL_VERSION}/modules.* /opt/lib/modules/${KERNEL_FULL_VERSION}/
RUN ln -s /lib/modules/${KERNEL_FULL_VERSION}/kernel /opt/lib/modules/${KERNEL_FULL_VERSION}/kernel
RUN mkdir -p /firmwareDir/updates/amdgpu
COPY --from=builder /lib/firmware/updates/amdgpu /firmwareDir/updates/amdgpu
29 changes: 29 additions & 0 deletions internal/kmmmodule/kmmmodule.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ var (
dockerfileTemplateUbuntu string
//go:embed dockerfiles/DockerfileTemplate.coreos
dockerfileTemplateCoreOS string
//go:embed dockerfiles/DockerfileTemplate.sles
dockerfileTemplateSLES string
//go:embed devdockerfiles/devdockerfile.txt
dockerfileDevTemplateUbuntu string
//go:embed dockerfiles/DockerfileTemplate.ubuntu.gim
Expand Down Expand Up @@ -230,6 +232,8 @@ func resolveDockerfile(cmName string, devConfig *amdv1alpha1.DeviceConfig) (stri
case utils.DriverTypeVFPassthrough:
dockerfileTemplate = dockerfileTemplateGIMCoreOS
}
case "sles":
dockerfileTemplate = dockerfileTemplateSLES
// FIX ME
// add the RHEL back when it is fully supported
/*case "rhel":
Expand All @@ -248,7 +252,11 @@ func resolveDockerfile(cmName string, devConfig *amdv1alpha1.DeviceConfig) (stri
// render base image registry
baseImageRegistry := defaultBaseImageRegistry
if devConfig.Spec.Driver.ImageBuild.BaseImageRegistry != "" {
// user-specified registry takes precendence
baseImageRegistry = devConfig.Spec.Driver.ImageBuild.BaseImageRegistry
} else if osDistro == "sles" {
// if OS == "sles", use default image registry as "registry.suse.com"
baseImageRegistry = "registry.suse.com"
}
dockerfileTemplate = strings.Replace(dockerfileTemplate, "$$BASEIMG_REGISTRY", baseImageRegistry, -1)
// render driver version
Expand Down Expand Up @@ -686,6 +694,8 @@ var cmNameMappers = map[string]func(fullImageStr string) string{
"rhel": rhelCMNameMapper,
"red hat": rhelCMNameMapper,
"redhat": rhelCMNameMapper,
"sles": slesCMNameMapper,
"suse": slesCMNameMapper,
}

func rhelCMNameMapper(osImageStr string) string {
Expand Down Expand Up @@ -719,6 +729,25 @@ func ubuntuCMNameMapper(osImageStr string) string {
return fmt.Sprintf("%s-%s", os, trimmedVersion)
}

func slesCMNameMapper(osImageStr string) string {
// Example: "SUSE Linux Enterprise Server 15 SP6" -> "sles-15.6"
// Example: "suse linux enterprise server 15-sp6" -> "sles-15.6"
// Convert to lowercase for consistent matching
osImageLower := strings.ToLower(osImageStr)
re := regexp.MustCompile(`(\d+)\s*-?\s*sp(\d+)`)
matches := re.FindStringSubmatch(osImageLower)
if len(matches) >= 3 {
return fmt.Sprintf("sles-%s.%s", matches[1], matches[2])
}
// Fallback for base version "SLES 15" or "SUSE Linux Enterprise Server 15"
re = regexp.MustCompile(`(\d+)`)
matches = re.FindStringSubmatch(osImageLower)
if len(matches) > 1 {
return fmt.Sprintf("sles-%s", matches[1])
}
return "sles-" + osImageLower
}

func GetK8SNodes(ctx context.Context, cli client.Client, labelSelector labels.Selector) (*v1.NodeList, error) {
options := &client.ListOptions{
LabelSelector: labelSelector,
Expand Down
57 changes: 57 additions & 0 deletions internal/kmmmodule/kmmmodule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -678,3 +678,60 @@ var _ = Describe("getKernelMappings", func() {
}
})
})

var _ = Describe("resolveDockerfile", func() {
It("should use correct default registry when not specified by user", func() {
testCases := []struct {
cmName string
expectedImageUrl string
}{
{"ubuntu-22.04", "docker.io/ubuntu:22.04"},
{"sles-15.6", "registry.suse.com/suse/sle15:15.6"},
}
for _, tc := range testCases {
input := &amdv1alpha1.DeviceConfig{
Spec: amdv1alpha1.DeviceConfigSpec{
Driver: amdv1alpha1.DriverSpec{},
},
}
dockerfile, err := resolveDockerfile(tc.cmName, input)
Expect(err).To(BeNil())
Expect(dockerfile).To(ContainSubstring(tc.expectedImageUrl))
}
})
It("should respect user-specified BaseImageRegistry for all OS types", func() {
testCases := []struct {
cmName string
expectedImageUrl string
}{
{"ubuntu-22.04", "example-image-registry.com/ubuntu:22.04"},
{"sles-15.6", "example-image-registry.com/suse/sle15:15.6"},
}
for _, tc := range testCases {
input := &amdv1alpha1.DeviceConfig{
Spec: amdv1alpha1.DeviceConfigSpec{
Driver: amdv1alpha1.DriverSpec{
ImageBuild: amdv1alpha1.ImageBuildSpec{
BaseImageRegistry: "example-image-registry.com",
},
},
},
}
dockerfile, err := resolveDockerfile(tc.cmName, input)
Expect(err).To(BeNil())
Expect(dockerfile).To(ContainSubstring(tc.expectedImageUrl))
Expect(dockerfile).NotTo(ContainSubstring("docker.io"))
Expect(dockerfile).NotTo(ContainSubstring("registry.suse.com"))
}
})
It("should return error for unsupported OS", func() {
input := &amdv1alpha1.DeviceConfig{
Spec: amdv1alpha1.DeviceConfigSpec{
Driver: amdv1alpha1.DriverSpec{},
},
}
_, err := resolveDockerfile("unsupported-os", input)
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring("not supported OS"))
})
})
23 changes: 23 additions & 0 deletions internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ var defaultDriverversionsMappers = map[string]func(fullImageStr string) (string,
"red hat": func(f string) (string, error) {
return defaultOcDriversVersion, nil
},
"sles": SLESDefaultDriverVersionsMapper,
"suse": SLESDefaultDriverVersionsMapper,
}

func UbuntuDefaultDriverVersionsMapper(fullImageStr string) (string, error) {
Expand Down Expand Up @@ -229,6 +231,27 @@ func UbuntuDefaultDriverVersionsMapper(fullImageStr string) (string, error) {
return "", fmt.Errorf("unsupported Ubuntu version: %s. Supported versions include 20.04, 22.04 and 24.04", fullImageStr)
}

func SLESDefaultDriverVersionsMapper(fullImageStr string) (string, error) {
// For SLES 15 SP6 and above, use the latest stable driver version
if strings.Contains(fullImageStr, "15") {
// Check for SP6 or later
re := regexp.MustCompile(`15\s*-?\s*sp(\d+)`)
match := re.FindStringSubmatch(strings.ToLower(fullImageStr))
if len(match) > 1 {
spVersion, err := strconv.Atoi(match[1])
if err == nil && spVersion >= 6 {
return "7.0.2", nil // Latest stable version for SP6+
}
if err == nil && spVersion >= 5 {
return "6.2.2", nil // Stable version for SP5
}
}
// Default for SLES 15 without SP info
return "6.2.2", nil
}
return "", fmt.Errorf("unsupported SLES version: %s. Supported versions include SLES 15 SP5 and above", fullImageStr)
}

func HasNodeLabelKey(node v1.Node, labelKey string) bool {
for k := range node.Labels {
if k == labelKey {
Expand Down
61 changes: 61 additions & 0 deletions internal/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,64 @@ func TestUbuntuDefaultDriverVersionsMapper(t *testing.T) {
})
}
}

func TestSLESDefaultDriverVersionsMapper(t *testing.T) {
tests := []struct {
name string
osImage string
expected string
wantErr bool
}{
{
name: "SLES 15 SP6",
osImage: "SUSE Linux Enterprise Server 15 SP6",
expected: "7.0.2",
wantErr: false,
},
{
name: "SLES 15 SP7",
osImage: "SUSE Linux Enterprise Server 15 SP7",
expected: "7.0.2",
wantErr: false,
},
{
name: "SLES 15 SP5",
osImage: "SUSE Linux Enterprise Server 15 SP5",
expected: "6.2.2",
wantErr: false,
},
{
name: "SLES 15 SP4",
osImage: "suse linux enterprise server 15 sp4",
expected: "6.2.2",
wantErr: false,
},
{
name: "SLES 15 base",
osImage: "SUSE Linux Enterprise Server 15",
expected: "6.2.2",
wantErr: false,
},
{
name: "SLES 15 with dash format",
osImage: "sles 15-sp6",
expected: "7.0.2",
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := SLESDefaultDriverVersionsMapper(tt.osImage)

if (err != nil) != tt.wantErr {
t.Errorf("SLESDefaultDriverVersionsMapper() error = %v, wantErr %v", err, tt.wantErr)
return
}

if result != tt.expected {
t.Errorf("SLESDefaultDriverVersionsMapper() = %q, want %q", result, tt.expected)
}
})
}
}