Skip to content
Closed
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
18 changes: 18 additions & 0 deletions api/nvidia/v1/clusterpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,10 @@ type DriverSpec struct {
// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Custom Repo Configuration For NVIDIA Driver Container"
RepoConfig *DriverRepoConfigSpec `json:"repoConfig,omitempty"`

// HostSubscription controls host subscription mounts independently of custom repositories.
// +optional
HostSubscription DriverHostSubscriptionSpec `json:"hostSubscription,omitempty"`

// Optional: Custom certificates configuration for NVIDIA Driver container
// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true
// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Custom Certificates Configuration For NVIDIA Driver Container"
Expand Down Expand Up @@ -1279,6 +1283,20 @@ type NodeStatusExporterSpec struct {
HostNetwork *bool `json:"hostNetwork,omitempty"`
}

// DriverHostSubscriptionSpec controls host subscription mounts for the NVIDIA driver container.
// OS and runtime eligibility checks still apply when mounts are enabled.
type DriverHostSubscriptionSpec struct {
// Enabled defaults to true when omitted. Set to false for air-gapped hosts
// without subscription files, even when custom repositories are configured.
// +optional
Enabled *bool `json:"enabled,omitempty"`
}

// IsEnabled preserves automatic host subscription mounts unless explicitly disabled.
func (h *DriverHostSubscriptionSpec) IsEnabled() bool {
return h.Enabled == nil || *h.Enabled
}

// DriverRepoConfigSpec defines custom repo configuration for NVIDIA Driver container
type DriverRepoConfigSpec struct {
// +kubebuilder:validation:Optional
Expand Down
28 changes: 28 additions & 0 deletions api/nvidia/v1/clusterpolicy_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package v1

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -86,3 +87,30 @@ func TestImagePath(t *testing.T) {
assert.ErrorContains(t, err, "invalid nil spec")
})
}

func TestDriverHostSubscriptionSpec(t *testing.T) {
for name, tc := range map[string]struct {
input string
enabled bool
omitted bool
}{
"omitted": {input: `{}`, enabled: true, omitted: true},
"enabled": {input: `{"enabled":true}`, enabled: true},
"disabled": {input: `{"enabled":false}`, enabled: false},
} {
t.Run(name, func(t *testing.T) {
var spec DriverHostSubscriptionSpec
require.NoError(t, json.Unmarshal([]byte(tc.input), &spec))
require.Equal(t, tc.enabled, spec.IsEnabled())
require.Equal(t, tc.omitted, spec.Enabled == nil)
encoded, err := json.Marshal(spec)
require.NoError(t, err)
require.JSONEq(t, tc.input, string(encoded))
copied := spec.DeepCopy()
if spec.Enabled != nil {
*copied.Enabled = !*copied.Enabled
require.Equal(t, tc.enabled, spec.IsEnabled())
}
})
}
}
21 changes: 21 additions & 0 deletions api/nvidia/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions api/nvidia/v1alpha1/nvidiadriver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ type NVIDIADriverSpec struct {
// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Custom Repo Configuration For NVIDIA Driver Container"
RepoConfig *DriverRepoConfigSpec `json:"repoConfig,omitempty"`

// HostSubscription controls host subscription mounts independently of custom repositories.
// +optional
HostSubscription DriverHostSubscriptionSpec `json:"hostSubscription,omitempty"`

// Optional: Custom certificates configuration for NVIDIA Driver container
// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true
// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName="Custom Certificates Configuration For NVIDIA Driver Container"
Expand Down Expand Up @@ -448,6 +452,20 @@ type DriverCertConfigSpec struct {
Name string `json:"name,omitempty"`
}

// DriverHostSubscriptionSpec controls host subscription mounts for the NVIDIA driver container.
// OS and runtime eligibility checks still apply when mounts are enabled.
type DriverHostSubscriptionSpec struct {
// Enabled defaults to true when omitted. Set to false for air-gapped hosts
// without subscription files, even when custom repositories are configured.
// +optional
Enabled *bool `json:"enabled,omitempty"`
}

// IsEnabled preserves automatic host subscription mounts unless explicitly disabled.
func (h *DriverHostSubscriptionSpec) IsEnabled() bool {
return h.Enabled == nil || *h.Enabled
}

// DriverRepoConfigSpec defines custom repo configuration for NVIDIA Driver container
type DriverRepoConfigSpec struct {
// +kubebuilder:validation:Optional
Expand Down
28 changes: 28 additions & 0 deletions api/nvidia/v1alpha1/nvidiadriver_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package v1alpha1

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -416,3 +417,30 @@ func TestGDRCopyGetImagePath(t *testing.T) {
})
}
}

func TestDriverHostSubscriptionSpec(t *testing.T) {
for name, tc := range map[string]struct {
input string
enabled bool
omitted bool
}{
"omitted": {input: `{}`, enabled: true, omitted: true},
"enabled": {input: `{"enabled":true}`, enabled: true},
"disabled": {input: `{"enabled":false}`, enabled: false},
} {
t.Run(name, func(t *testing.T) {
var spec DriverHostSubscriptionSpec
require.NoError(t, json.Unmarshal([]byte(tc.input), &spec))
require.Equal(t, tc.enabled, spec.IsEnabled())
require.Equal(t, tc.omitted, spec.Enabled == nil)
encoded, err := json.Marshal(spec)
require.NoError(t, err)
require.JSONEq(t, tc.input, string(encoded))
copied := spec.DeepCopy()
if spec.Enabled != nil {
*copied.Enabled = !*copied.Enabled
require.Equal(t, tc.enabled, spec.IsEnabled())
}
})
}
}
21 changes: 21 additions & 0 deletions api/nvidia/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions bundle/manifests/nvidia.com_clusterpolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,16 @@ spec:
description: HostNetwork indicates whether the Driver pod uses
the host's network namespace.
type: boolean
hostSubscription:
description: HostSubscription controls host subscription mounts
independently of custom repositories.
properties:
enabled:
description: |-
Enabled defaults to true when omitted. Set to false for air-gapped hosts
without subscription files, even when custom repositories are configured.
type: boolean
type: object
image:
description: NVIDIA Driver image name
pattern: '[a-zA-Z0-9\-]+'
Expand Down
10 changes: 10 additions & 0 deletions bundle/manifests/nvidia.com_nvidiadrivers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ spec:
description: HostNetwork indicates whether the Driver pod uses the
host's network namespace.
type: boolean
hostSubscription:
description: HostSubscription controls host subscription mounts independently
of custom repositories.
properties:
enabled:
description: |-
Enabled defaults to true when omitted. Set to false for air-gapped hosts
without subscription files, even when custom repositories are configured.
type: boolean
type: object
image:
default: nvcr.io/nvidia/driver
description: NVIDIA Driver container image name
Expand Down
10 changes: 10 additions & 0 deletions config/crd/bases/nvidia.com_clusterpolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,16 @@ spec:
description: HostNetwork indicates whether the Driver pod uses
the host's network namespace.
type: boolean
hostSubscription:
description: HostSubscription controls host subscription mounts
independently of custom repositories.
properties:
enabled:
description: |-
Enabled defaults to true when omitted. Set to false for air-gapped hosts
without subscription files, even when custom repositories are configured.
type: boolean
type: object
image:
description: NVIDIA Driver image name
pattern: '[a-zA-Z0-9\-]+'
Expand Down
10 changes: 10 additions & 0 deletions config/crd/bases/nvidia.com_nvidiadrivers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ spec:
description: HostNetwork indicates whether the Driver pod uses the
host's network namespace.
type: boolean
hostSubscription:
description: HostSubscription controls host subscription mounts independently
of custom repositories.
properties:
enabled:
description: |-
Enabled defaults to true when omitted. Set to false for air-gapped hosts
without subscription files, even when custom repositories are configured.
type: boolean
type: object
image:
default: nvcr.io/nvidia/driver
description: NVIDIA Driver container image name
Expand Down
4 changes: 2 additions & 2 deletions controllers/object_controls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3778,8 +3778,8 @@ func transformDriverContainer(obj *appsv1.DaemonSet, config *gpuv1.ClusterPolicy
// set up subscription entitlements for RHEL(using K8s with a non-CRIO runtime) and SLES
if (osID == "rhel" && n.openshift == "" && n.runtime != gpuv1.CRIO) || osID == "sles" || osID == "sl-micro" {
pathToVolumeSource := MountPathToVolumeSource{}
if config.Driver.RepoConfig != nil && config.Driver.RepoConfig.ConfigMapName != "" && osID == "rhel" {
n.logger.Info("Skipping host subscription mounts because repoConfig is enabled", "OS", osID)
if !config.Driver.HostSubscription.IsEnabled() {
n.logger.Info("Skipping host subscription mounts because hostSubscription is disabled", "OS", osID)
Comment on lines +3781 to +3782

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Existing air-gapped RHEL driver pods fail

On RHEL hosts with repoConfig but missing subscription files, omitted hostSubscription now adds mandatory hostPath mounts. Existing driver pods fail to start after upgrade.

Learn more

Both driver render paths previously omitted RHEL subscription mounts when a custom repository was configured. The new default enables those mounts even for existing custom-repository installations. The subscription paths require host files and directories, so Kubernetes cannot start the pod on an air-gapped node where they do not exist. The same condition changed in getDriverAdditionalConfigs.

Example: A RHEL node has a custom repository ConfigMap but no /etc/pki/entitlement. Before upgrade its driver pod starts without subscription mounts. After upgrade, its unchanged resource produces a required /etc/pki/entitlement hostPath and the driver pod cannot start.

Recommended fix: Preserve the old skip behavior when hostSubscription.enabled is omitted and repoConfig is configured on RHEL, in both transformDriverContainer and getDriverAdditionalConfigs. Allow explicit true to mount both and explicit false to skip. If changing the omitted default is necessary, provide a migration that keeps existing installations running.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

} else {
n.logger.Info("Mounting subscriptions into the driver container", "OS", osID)
pathToVolumeSource, err = n.getSubscriptionPathsToVolumeSources()
Expand Down
Loading
Loading