Compare commits

...

1 Commits

Author SHA1 Message Date
Dan Mihai
1901c9b841 DO NOT MERGE: CI test
Test of the ci-devel pipeline
2025-12-19 09:56:15 +00:00
5 changed files with 84 additions and 35 deletions

View File

@@ -157,7 +157,7 @@ func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest) (*con
s.config.SandboxCPUs, s.config.SandboxMemMB = oci.CalculateContainerSizing(ociSpec) s.config.SandboxCPUs, s.config.SandboxMemMB = oci.CalculateContainerSizing(ociSpec)
} }
if rootFs.Mounted, err = checkAndMount(s, r); err != nil { if rootFs.Mounted, rootFs.PluggedBlockDevice, err = checkAndMount(s, r); err != nil {
return nil, err return nil, err
} }
@@ -211,7 +211,7 @@ func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest) (*con
return nil, fmt.Errorf("BUG: Cannot start the container, since the sandbox hasn't been created") return nil, fmt.Errorf("BUG: Cannot start the container, since the sandbox hasn't been created")
} }
if rootFs.Mounted, err = checkAndMount(s, r); err != nil { if rootFs.Mounted, rootFs.PluggedBlockDevice, err = checkAndMount(s, r); err != nil {
return nil, err return nil, err
} }
@@ -308,33 +308,39 @@ func loadRuntimeConfig(s *service, r *taskAPI.CreateTaskRequest, anno map[string
return &runtimeConfig, nil return &runtimeConfig, nil
} }
func checkAndMount(s *service, r *taskAPI.CreateTaskRequest) (bool, error) { func checkAndMount(s *service, r *taskAPI.CreateTaskRequest) (bool, bool, error) {
mounted := false
pluggedBlockDevice := false
if len(r.Rootfs) == 1 { if len(r.Rootfs) == 1 {
m := r.Rootfs[0] m := r.Rootfs[0]
// Plug the block backed rootfs directly instead of mounting it. // Plug the block backed rootfs directly instead of mounting it.
if katautils.IsBlockDevice(m.Source) && !s.config.HypervisorConfig.DisableBlockDeviceUse { if katautils.IsBlockDevice(m.Source) && !s.config.HypervisorConfig.DisableBlockDeviceUse {
return false, nil pluggedBlockDevice = true
return mounted, pluggedBlockDevice, nil
} }
if virtcontainers.HasOptionPrefix(m.Options, annotations.FileSystemLayer) { if virtcontainers.HasOptionPrefix(m.Options, annotations.FileSystemLayer) {
return false, nil return mounted, pluggedBlockDevice, nil
} }
if virtcontainers.IsErofsRootFS(virtcontainers.RootFs{Options: m.Options, Type: m.Type}) { if virtcontainers.IsErofsRootFS(virtcontainers.RootFs{Options: m.Options, Type: m.Type}) {
return false, nil return mounted, pluggedBlockDevice, nil
} }
if vc.IsNydusRootFSType(m.Type) { if vc.IsNydusRootFSType(m.Type) {
// if kata + nydus, do not mount // if kata + nydus, do not mount
return false, nil return mounted, pluggedBlockDevice, nil
} }
} }
rootfs := filepath.Join(r.Bundle, "rootfs") rootfs := filepath.Join(r.Bundle, "rootfs")
if err := doMount(r.Rootfs, rootfs); err != nil { if err := doMount(r.Rootfs, rootfs); err != nil {
return false, err return mounted, pluggedBlockDevice, err
} }
return true, nil
mounted = true
return mounted, pluggedBlockDevice, nil
} }
func doMount(mounts []*containerd_types.Mount, rootfs string) error { func doMount(mounts []*containerd_types.Mount, rootfs string) error {

View File

@@ -27,7 +27,6 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols/grpc" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols/grpc"
vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations" vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
"github.com/moby/sys/mountinfo" "github.com/moby/sys/mountinfo"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -319,6 +318,8 @@ type RootFs struct {
Options []string Options []string
// Mounted specifies whether the rootfs has be mounted or not // Mounted specifies whether the rootfs has be mounted or not
Mounted bool Mounted bool
// PluggedBlockDevice specifies whether Source should be plugged into the Guest as block block.
PluggedBlockDevice bool
} }
// Container is composed of a set of containers and a runtime environment. // Container is composed of a set of containers and a runtime environment.
@@ -1237,7 +1238,7 @@ func (c *Container) create(ctx context.Context) (err error) {
} }
}() }()
if c.checkBlockDeviceSupport(ctx) && !IsNydusRootFSType(c.rootFs.Type) && !IsErofsRootFS(c.rootFs) { if c.checkBlockDeviceSupport(ctx) {
// If the rootfs is backed by a block device, go ahead and hotplug it to the guest // If the rootfs is backed by a block device, go ahead and hotplug it to the guest
if err = c.hotplugDrive(ctx); err != nil { if err = c.hotplugDrive(ctx); err != nil {
return return
@@ -1586,19 +1587,21 @@ func (c *Container) resume(ctx context.Context) error {
// hotplugDrive will attempt to hotplug the container rootfs if it is backed by a // hotplugDrive will attempt to hotplug the container rootfs if it is backed by a
// block device // block device
func (c *Container) hotplugDrive(ctx context.Context) error { func (c *Container) hotplugDrive(ctx context.Context) error {
var dev device c.Logger().WithFields(logrus.Fields{
var err error "rootfs-source": c.rootFs.Source,
"rootfs-mounted": c.rootFs.Mounted,
"plugged-device": c.rootFs.PluggedBlockDevice,
}).Info("rootfs properties")
// Check to see if the rootfs is an umounted block device (source) or if the if !c.rootFs.PluggedBlockDevice {
// mount (target) is backed by a block device: return nil
if !c.rootFs.Mounted {
dev, err = getDeviceForPath(c.rootFs.Source)
// there is no "rootfs" dir on block device backed rootfs
c.rootfsSuffix = ""
} else {
dev, err = getDeviceForPath(c.rootFs.Target)
} }
if c.rootFs.Mounted {
panic("Mounted cannot be true when PluggedBlockDevice is true")
}
dev, err := getDeviceForPath(c.rootFs.Source)
if err == errMountPointNotFound { if err == errMountPointNotFound {
return nil return nil
} }
@@ -1607,6 +1610,8 @@ func (c *Container) hotplugDrive(ctx context.Context) error {
return err return err
} }
c.rootfsSuffix = ""
c.Logger().WithFields(logrus.Fields{ c.Logger().WithFields(logrus.Fields{
"device-major": dev.major, "device-major": dev.major,
"device-minor": dev.minor, "device-minor": dev.minor,
@@ -1622,23 +1627,11 @@ func (c *Container) hotplugDrive(ctx context.Context) error {
return nil return nil
} }
devicePath := c.rootFs.Source devicePath, err := filepath.EvalSymlinks(c.rootFs.Source)
fsType := c.rootFs.Type
if c.rootFs.Mounted {
if dev.mountPoint == c.rootFs.Target {
c.rootfsSuffix = ""
}
// If device mapper device, then fetch the full path of the device
devicePath, fsType, _, err = utils.GetDevicePathAndFsTypeOptions(dev.mountPoint)
if err != nil {
return err
}
}
devicePath, err = filepath.EvalSymlinks(devicePath)
if err != nil { if err != nil {
return err return err
} }
fsType := c.rootFs.Type
c.Logger().WithFields(logrus.Fields{ c.Logger().WithFields(logrus.Fields{
"device-path": devicePath, "device-path": devicePath,

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bats
#
# Copyright (c) 2025 NVIDIA Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
load "${BATS_TEST_DIRNAME}/../../common.bash"
load "${BATS_TEST_DIRNAME}/lib.sh"
load "${BATS_TEST_DIRNAME}/tests_common.sh"
setup() {
setup_common || die "setup_common failed"
pod_name="no-layer-image"
get_pod_config_dir
yaml_file="${pod_config_dir}/${pod_name}.yaml"
auto_generate_policy "${pod_config_dir}" "${yaml_file}"
}
@test "Test image with no layers cannot run" {
assert_pod_fail "${yaml_file}"
kubectl get pods "${pod_name}" -o jsonpath='{.status.containerStatuses[0].lastState.terminated.message}' | grep "the file sleep was not found"
}
teardown() {
# Debugging information
kubectl describe "pod/${pod_name}"
kubectl get "pod/${pod_name}" -o yaml
kubectl delete pod "${pod_name}"
node_end_time "${node}"
echo "setup_common starts at ${node_start_time:-}, teardown_common ends at ${node_end_time:-}"
teardown_common "${node}" "${node_start_time:-}"
}

View File

@@ -42,6 +42,7 @@ else
) )
K8S_TEST_SMALL_HOST_UNION=( \ K8S_TEST_SMALL_HOST_UNION=( \
"k8s-empty-image.bats" \
"k8s-guest-pull-image.bats" \ "k8s-guest-pull-image.bats" \
"k8s-confidential.bats" \ "k8s-confidential.bats" \
"k8s-sealed-secret.bats" \ "k8s-sealed-secret.bats" \

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: no-layer-image
spec:
runtimeClassName: kata
containers:
- name: no-layer-image
image: ghcr.io/kata-containers/no-layer-image:latest
resources: {}
command:
- sleep
- infinity