diff --git a/src/runtime/pkg/containerd-shim-v2/device_cold_plug.go b/src/runtime/pkg/containerd-shim-v2/device_cold_plug.go index 0b13730634..bf35cad66c 100644 --- a/src/runtime/pkg/containerd-shim-v2/device_cold_plug.go +++ b/src/runtime/pkg/containerd-shim-v2/device_cold_plug.go @@ -9,6 +9,7 @@ import ( "context" "fmt" "net" + "os" "strings" "github.com/kata-containers/kata-containers/src/runtime/pkg/device/config" @@ -39,12 +40,15 @@ func coldPlugDevices(ctx context.Context, s *service, ociSpec *specs.Spec) error return nil } - kubeletSock := s.config.PodResourceAPISock - if kubeletSock != "" { + if kubeletPodResourceSocketAvailable(s.config.PodResourceAPISock) { return coldPlugWithAPI(ctx, s, ociSpec) } - shimLog.Debug("config.PodResourceAPISock not set, skip k8s based device cold plug") + if s.config.PodResourceAPISock != "" { + shimLog.Debugf("config.PodResourceAPISock %q not available, fall back to CDI annotations", s.config.PodResourceAPISock) + } else { + shimLog.Debug("config.PodResourceAPISock not set, use CDI annotations for cold plug") + } // Here we deal with CDI devices that are cold-plugged // for the single_container (nerdctl, podman, ...) use-case. @@ -58,6 +62,20 @@ func coldPlugDevices(ctx context.Context, s *service, ociSpec *specs.Spec) error return nil } +// kubeletPodResourceSocketAvailable reports whether the configured kubelet Pod +// Resources API socket exists and can be used for Kubernetes-based cold plug. +func kubeletPodResourceSocketAvailable(sock string) bool { + if sock == "" { + return false + } + fi, err := os.Stat(sock) + if err != nil { + return false + } + + return (fi.Mode() & os.ModeSocket) != 0 +} + func coldPlugWithAPI(ctx context.Context, s *service, ociSpec *specs.Spec) error { ann := ociSpec.Annotations devices, err := getDeviceSpec(ctx, s.config.PodResourceAPISock, ann) diff --git a/src/runtime/pkg/containerd-shim-v2/device_cold_plug_test.go b/src/runtime/pkg/containerd-shim-v2/device_cold_plug_test.go new file mode 100644 index 0000000000..c914cb7348 --- /dev/null +++ b/src/runtime/pkg/containerd-shim-v2/device_cold_plug_test.go @@ -0,0 +1,36 @@ +// Copyright (c) 2025 NVIDIA CORPORATION. +// +// SPDX-License-Identifier: Apache-2.0 +// + +package containerdshim + +import ( + "net" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKubeletPodResourceSocketAvailable(t *testing.T) { + assert.False(t, kubeletPodResourceSocketAvailable("")) + + tmpDir := t.TempDir() + sockPath := filepath.Join(tmpDir, "kubelet.sock") + assert.False(t, kubeletPodResourceSocketAvailable(sockPath)) + + f, err := os.Create(sockPath) + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + assert.False(t, kubeletPodResourceSocketAvailable(sockPath)) + + assert.NoError(t, os.Remove(sockPath)) + l, err := net.Listen("unix", sockPath) + assert.NoError(t, err) + defer l.Close() + + assert.True(t, kubeletPodResourceSocketAvailable(sockPath)) +}