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
23 changes: 11 additions & 12 deletions cmd/dra-example-kubeletplugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (

"sigs.k8s.io/dra-example-driver/internal/profiles"
"sigs.k8s.io/dra-example-driver/internal/profiles/gpu"
"sigs.k8s.io/dra-example-driver/pkg/featuregates"
"sigs.k8s.io/dra-example-driver/pkg/flags"
)

Expand All @@ -50,7 +51,6 @@ type Flags struct {
kubeletRegistrarDirectoryPath string
kubeletPluginsDirectoryPath string
healthcheckPort int
profile string
driverName string
podUID string
gpuPartitions int
Expand Down Expand Up @@ -138,16 +138,9 @@ func newApp() *cli.App {
Destination: &flags.healthcheckPort,
EnvVars: []string{"HEALTHCHECK_PORT"},
},
&cli.StringFlag{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

we can keep this flag right?

we should document with vfio that the profile will be changed to vfio automatically

Name: "device-profile",
Usage: fmt.Sprintf("Name of the device profile. Valid values are %q.", validProfileNames),
Value: gpu.ProfileName,
Destination: &flags.profile,
EnvVars: []string{"DEVICE_PROFILE"},
},
&cli.StringFlag{
Name: "driver-name",
Usage: "Name of the DRA driver. Its default is derived from the device profile.",
Usage: "Name of the DRA driver. Its default is derived from the active device profile.",
Destination: &flags.driverName,
EnvVars: []string{"DRIVER_NAME"},
},
Expand Down Expand Up @@ -200,13 +193,19 @@ func newApp() *cli.App {
return fmt.Errorf("create client: %w", err)
}

profile := featuregates.DeviceProfile()

if flags.driverName == "" {
flags.driverName = flags.profile + ".example.com"
flags.driverName = profile + ".example.com"
}

newProfile, ok := validProfiles[flags.profile]
newProfile, ok := validProfiles[profile]
if !ok {
return fmt.Errorf("invalid device profile %q, valid profiles are %q", flags.profile, validProfileNames)
var valid []string
for profileName := range validProfiles {
valid = append(valid, profileName)
}
return fmt.Errorf("invalid device profile %q, valid profiles are %q", profile, valid)
}

config := &Config{
Expand Down
3 changes: 2 additions & 1 deletion cmd/dra-example-kubeletplugin/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
checkpointinstall "sigs.k8s.io/dra-example-driver/internal/api/checkpoint/install"
checkpointv1alpha1 "sigs.k8s.io/dra-example-driver/internal/api/checkpoint/v1"
"sigs.k8s.io/dra-example-driver/internal/profiles"
"sigs.k8s.io/dra-example-driver/pkg/featuregates"
)

type AllocatableDevices map[string]resourceapi.Device
Expand Down Expand Up @@ -90,7 +91,7 @@ func NewDeviceState(config *Config) (*DeviceState, error) {
return nil, fmt.Errorf("error enumerating all possible devices: %v", err)
}

cdi, err := NewCDIHandler(config.flags.cdiRoot, config.flags.driverName, config.flags.profile)
cdi, err := NewCDIHandler(config.flags.cdiRoot, config.flags.driverName, featuregates.DeviceProfile())
if err != nil {
return nil, fmt.Errorf("unable to create CDI handler: %v", err)
}
Expand Down
18 changes: 6 additions & 12 deletions cmd/dra-example-webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

"sigs.k8s.io/dra-example-driver/internal/profiles"
"sigs.k8s.io/dra-example-driver/internal/profiles/gpu"
"sigs.k8s.io/dra-example-driver/pkg/featuregates"
"sigs.k8s.io/dra-example-driver/pkg/flags"
)

Expand All @@ -45,7 +46,6 @@ type Flags struct {
certFile string
keyFile string
port int
profile string
driverName string
}

Expand Down Expand Up @@ -85,16 +85,9 @@ func newApp() *cli.App {
Value: 443,
Destination: &flags.port,
},
&cli.StringFlag{
Name: "device-profile",
Usage: fmt.Sprintf("Name of the device profile. Valid values are %q.", validProfiles),
Value: gpu.ProfileName,
Destination: &flags.profile,
EnvVars: []string{"DEVICE_PROFILE"},
},
&cli.StringFlag{
Name: "driver-name",
Usage: "Name of the DRA driver. Its default is derived from the device profile.",
Usage: "Name of the DRA driver. Its default is derived from the active device profile.",
Destination: &flags.driverName,
EnvVars: []string{"DRIVER_NAME"},
},
Expand All @@ -114,17 +107,18 @@ func newApp() *cli.App {
return flags.loggingConfig.Apply()
},
Action: func(c *cli.Context) error {
configHandler, ok := validProfiles[flags.profile]
profile := featuregates.DeviceProfile()
configHandler, ok := validProfiles[profile]
if !ok {
var valid []string
for profileName := range validProfiles {
valid = append(valid, profileName)
}
return fmt.Errorf("invalid device profile %q, valid profiles are %q", flags.profile, valid)
return fmt.Errorf("invalid device profile %q, valid profiles are %q", profile, valid)
}

if flags.driverName == "" {
flags.driverName = flags.profile + ".example.com"
flags.driverName = profile + ".example.com"
}

mux, err := newMux(configHandler, flags.driverName)
Expand Down
6 changes: 5 additions & 1 deletion deployments/helm/dra-example-driver/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,9 @@ resource.k8s.io/v1beta1
The driver name.
*/}}
{{- define "dra-example-driver.driverName" -}}
{{ default (print .Values.deviceProfile ".example.com") .Values.driverName }}
{{- if .Values.driverName -}}
{{- .Values.driverName -}}
{{- else -}}
gpu.example.com
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ spec:
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["dra-example-controller"]
args:
- --driver-name={{ include "dra-example-driver.driverName" . }}
{{- if .Values.driverName }}
- --driver-name={{ .Values.driverName }}
{{- end }}
{{- range .Values.controller.plugins }}
- --enable-plugin={{ . }}
{{- end }}
Expand Down
10 changes: 7 additions & 3 deletions deployments/helm/dra-example-driver/templates/kubeletplugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,14 @@ spec:
periodSeconds: 10
{{- end }}
env:
{{- if .Values.driverName }}
- name: DRIVER_NAME
value: {{ include "dra-example-driver.driverName" . | quote }}
- name: DEVICE_PROFILE
value: {{ .Values.deviceProfile | quote }}
value: {{ .Values.driverName | quote }}
{{- end }}
{{- if .Values.featureGates }}
- name: FEATURE_GATES
value: "{{ range $key, $value := .Values.featureGates }}{{ $key }}={{ $value }},{{ end }}"
{{- end }}
- name: CDI_ROOT
value: /var/run/cdi
- name: KUBELET_REGISTRAR_DIRECTORY_PATH
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,14 @@ spec:
- --tls-cert-file=/cert/tls.crt
- --tls-private-key-file=/cert/tls.key
- --port={{ .Values.webhook.containerPort }}
- --device-profile={{ .Values.deviceProfile }}
- --driver-name={{ include "dra-example-driver.driverName" . }}
{{- if .Values.driverName }}
- --driver-name={{ .Values.driverName }}
{{- end }}
{{- if .Values.featureGates }}
env:
- name: FEATURE_GATES
value: "{{ range $key, $value := .Values.featureGates }}{{ $key }}={{ $value }},{{ end }}"
{{- end }}
ports:
- name: webhook
containerPort: {{ .Values.webhook.containerPort }}
Expand Down
10 changes: 5 additions & 5 deletions deployments/helm/dra-example-driver/values.schema.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"type": "object",
"properties": {
"deviceProfile": {
"type": "string",
"enum": [
"gpu"
]
"featureGates": {
"type": "object",
"additionalProperties": {
"type": "boolean"
}
}
}
}
20 changes: 13 additions & 7 deletions deployments/helm/dra-example-driver/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ selectorLabelsOverride: {}

allowDefaultNamespace: false

# deviceProfile describes the overall shape of the devices managed by the
# driver. Available profiles are:
# - "gpu": Node-local devices configurable through opaque config
deviceProfile: "gpu"
# featureGates enables alpha/experimental driver behavior. Each entry is
# passed to components as FEATURE_GATES (comma-separated key=value pairs).
#
# VFIOGPUEnabled is recognized but not yet supported by this chart. Enabling it
# fails at install time until the vfio-gpu profile is added.
#
# Without feature gates, the default gpu profile is used (gpu.example.com).
featureGates: {}

# driverName uniquely identifies the driver within the cluster. When empty, its
# value is derived from the deviceProfile.
# driverName uniquely identifies the driver within the cluster. Leave empty for
# the driver components to derive it from the active device profile. The chart
# derives the same default for Kubernetes resources that need the name at render
# time. vfio-gpu.* driver names are not supported yet.
driverName: ""

# deviceClass configures the DeviceClass the driver creates for its devices.
Expand Down Expand Up @@ -50,7 +56,7 @@ serviceAccount:

kubeletPlugin:
# numDevices describes how many GPUs to advertise on each node when the "gpu"
# deviceProfile is used. Not relevant for other profiles.
# profile is used. Not relevant for other profiles.
numDevices: 8
# gpuPartitions sets the number of partitions per GPU. When set to a value
# greater than 0, GPUs are exposed with shared counters allowing flexible
Expand Down
93 changes: 93 additions & 0 deletions pkg/featuregates/featuregates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright The Kubernetes Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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.
*/

package featuregates

import (
"sync"

utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/component-base/featuregate"
logsapi "k8s.io/component-base/logs/api/v1"
)

// featureGateEmulationVersion must use Kubernetes-style versions (major.minor
// matching the vendored k8s.io/* release), not driver SemVer. Driver-local
// gates use 0.x Version fields and remain visible because 0.x < 1.y.
var featureGateEmulationVersion = version.MajorMinor(1, 36)

const (
// VFIOGPUEnabled enables PCI passthrough device discovery and preparation via
// the vfio-gpu profile. When enabled, the driver selects that profile
// instead of the default gpu profile.
VFIOGPUEnabled featuregate.Feature = "VFIOGPUEnabled"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is bleeding in from the other PR? Should this be left out?

)

var defaultFeatureGates = map[featuregate.Feature]featuregate.VersionedSpecs{
VFIOGPUEnabled: {
{
Default: false,
PreRelease: featuregate.Alpha,
Version: version.MajorMinor(0, 1),
},
},
}

var (
featureGatesOnce sync.Once
featureGates featuregate.MutableVersionedFeatureGate
)

// FeatureGates returns the process-wide feature gate set, including logging
// gates from component-base and driver-specific gates.
func FeatureGates() featuregate.MutableVersionedFeatureGate {
if featureGates == nil {
featureGatesOnce.Do(func() {
featureGates = newFeatureGates(featureGateEmulationVersion)
})
}
return featureGates
}

func newFeatureGates(v *version.Version) featuregate.MutableVersionedFeatureGate {
fg := featuregate.NewVersionedFeatureGate(v)
utilruntime.Must(logsapi.AddFeatureGates(fg))
utilruntime.Must(fg.AddVersioned(defaultFeatureGates))
utilruntime.Must(fg.SetFromMap(map[string]bool{
string(logsapi.ContextualLogging): true,
}))
return fg
}

// Enabled reports whether feature is enabled on the process-wide gate set.
func Enabled(feature featuregate.Feature) bool {
return FeatureGates().Enabled(feature)
}

const (
profileGPU = "gpu"
profileVFIOGPU = "vfio-gpu"
)

// DeviceProfile returns the active device profile. VFIOGPUEnabled selects vfio-gpu;
// otherwise the default gpu profile is used.
func DeviceProfile() string {
if Enabled(VFIOGPUEnabled) {
return profileVFIOGPU
}
return profileGPU
}
Loading