mirror of
https://github.com/containers/podman.git
synced 2025-06-25 12:20:42 +08:00
add tests and fix bug when char device pass the test as block device
- add test - fix bug when a character device set in a volume as a block device is seen as block device in _pkg/specgen/generate/kube/volume.go_. At this stage the type does not matter much because the devices are recreated at lower layer but the bug allowed a CharDevice volume to be passed to lower layer as a BlockDevice. Signed-off-by: Cosmin Tupangiu <cosmin@redhat.com>
This commit is contained in:
@ -382,7 +382,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
|||||||
}
|
}
|
||||||
s.Volumes = append(s.Volumes, &cmVolume)
|
s.Volumes = append(s.Volumes, &cmVolume)
|
||||||
case KubeVolumeTypeCharDevice:
|
case KubeVolumeTypeCharDevice:
|
||||||
// We are setting the path as hostPath:mountPath to comply with DeviceFromPath (https://github.com/containers/podman/blob/eb26fa45f1326191dea27f2afabf82cb8b934140/pkg/specgen/generate/config_linux.go#L72)
|
// We are setting the path as hostPath:mountPath to comply with pkg/specgen/generate.DeviceFromPath.
|
||||||
// The type is here just to improve readability as it is not taken into account when the actual device is created.
|
// The type is here just to improve readability as it is not taken into account when the actual device is created.
|
||||||
device := spec.LinuxDevice{
|
device := spec.LinuxDevice{
|
||||||
Path: fmt.Sprintf("%s:%s", volumeSource.Source, volume.MountPath),
|
Path: fmt.Sprintf("%s:%s", volumeSource.Source, volume.MountPath),
|
||||||
@ -390,7 +390,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
|||||||
}
|
}
|
||||||
s.Devices = append(s.Devices, device)
|
s.Devices = append(s.Devices, device)
|
||||||
case KubeVolumeTypeBlockDevice:
|
case KubeVolumeTypeBlockDevice:
|
||||||
// We are setting the path as hostPath:mountPath to comply with DeviceFromPath (https://github.com/containers/podman/blob/eb26fa45f1326191dea27f2afabf82cb8b934140/pkg/specgen/generate/config_linux.go#L72)
|
// We are setting the path as hostPath:mountPath to comply with pkg/specgen/generate.DeviceFromPath.
|
||||||
// The type is here just to improve readability as it is not taken into account when the actual device is created.
|
// The type is here just to improve readability as it is not taken into account when the actual device is created.
|
||||||
device := spec.LinuxDevice{
|
device := spec.LinuxDevice{
|
||||||
Path: fmt.Sprintf("%s:%s", volumeSource.Source, volume.MountPath),
|
Path: fmt.Sprintf("%s:%s", volumeSource.Source, volume.MountPath),
|
||||||
|
@ -85,8 +85,8 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error checking HostPathBlockDevice")
|
return nil, errors.Wrap(err, "error checking HostPathBlockDevice")
|
||||||
}
|
}
|
||||||
if dev.Mode()&os.ModeDevice != os.ModeDevice {
|
if dev.Mode()&os.ModeCharDevice == os.ModeCharDevice {
|
||||||
return nil, errors.Errorf("checking HosPathDevice: path %s is not a block device", hostPath.Path)
|
return nil, errors.Errorf("checking HostPathDevice: path %s is not a block device", hostPath.Path)
|
||||||
}
|
}
|
||||||
return &KubeVolume{
|
return &KubeVolume{
|
||||||
Type: KubeVolumeTypeBlockDevice,
|
Type: KubeVolumeTypeBlockDevice,
|
||||||
@ -98,7 +98,7 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
|
|||||||
return nil, errors.Wrap(err, "error checking HostPathCharDevice")
|
return nil, errors.Wrap(err, "error checking HostPathCharDevice")
|
||||||
}
|
}
|
||||||
if dev.Mode()&os.ModeCharDevice != os.ModeCharDevice {
|
if dev.Mode()&os.ModeCharDevice != os.ModeCharDevice {
|
||||||
return nil, errors.Errorf("checking HosPathCharDevice: path %s is not a character device", hostPath.Path)
|
return nil, errors.Errorf("checking HostPathCharDevice: path %s is not a character device", hostPath.Path)
|
||||||
}
|
}
|
||||||
return &KubeVolume{
|
return &KubeVolume{
|
||||||
Type: KubeVolumeTypeCharDevice,
|
Type: KubeVolumeTypeCharDevice,
|
||||||
|
@ -3685,4 +3685,131 @@ ENV OPENJ9_JAVA_OPTIONS=%q
|
|||||||
Expect(usernsInCtr).Should(Exit(0))
|
Expect(usernsInCtr).Should(Exit(0))
|
||||||
Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig))))
|
Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig))))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Check the block devices are exposed inside container
|
||||||
|
It("podman play kube expose block device inside container", func() {
|
||||||
|
SkipIfRootless("It needs root access to create devices")
|
||||||
|
Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
|
||||||
|
defer os.RemoveAll("/dev/foodevdir")
|
||||||
|
|
||||||
|
devicePath := "/dev/foodevdir/blockdevice"
|
||||||
|
mknod := SystemExec("mknod", []string{devicePath, "b", "7", "0"})
|
||||||
|
mknod.WaitWithDefaultTimeout()
|
||||||
|
Expect(mknod).Should(Exit(0))
|
||||||
|
|
||||||
|
blockVolume := getHostPathVolume("BlockDevice", devicePath)
|
||||||
|
|
||||||
|
pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false))))
|
||||||
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
// Container should be in running state
|
||||||
|
inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("running"))
|
||||||
|
|
||||||
|
// Container should have a block device /dev/loop1
|
||||||
|
inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.Devices}}", "testPod-" + defaultCtrName})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring(devicePath))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check the char devices are exposed inside container
|
||||||
|
It("podman play kube expose character device inside container", func() {
|
||||||
|
SkipIfRootless("It needs root access to create devices")
|
||||||
|
Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
|
||||||
|
defer os.RemoveAll("/dev/foodevdir")
|
||||||
|
|
||||||
|
devicePath := "/dev/foodevdir/chardevice"
|
||||||
|
mknod := SystemExec("mknod", []string{devicePath, "c", "3", "1"})
|
||||||
|
mknod.WaitWithDefaultTimeout()
|
||||||
|
Expect(mknod).Should(Exit(0))
|
||||||
|
|
||||||
|
charVolume := getHostPathVolume("CharDevice", devicePath)
|
||||||
|
|
||||||
|
pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false))))
|
||||||
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
// Container should be in running state
|
||||||
|
inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.State.Status}}", "testPod-" + defaultCtrName})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("running"))
|
||||||
|
|
||||||
|
// Container should have a block device /dev/loop1
|
||||||
|
inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.Devices}}", "testPod-" + defaultCtrName})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring(devicePath))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman play kube reports error when the device does not exists", func() {
|
||||||
|
SkipIfRootless("It needs root access to create devices")
|
||||||
|
|
||||||
|
devicePath := "/dev/foodevdir/baddevice"
|
||||||
|
|
||||||
|
blockVolume := getHostPathVolume("BlockDevice", devicePath)
|
||||||
|
|
||||||
|
pod := getPod(withVolume(blockVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false))))
|
||||||
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(125))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman play kube reports error when we try to expose char device as block device", func() {
|
||||||
|
SkipIfRootless("It needs root access to create devices")
|
||||||
|
Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
|
||||||
|
defer os.RemoveAll("/dev/foodevdir")
|
||||||
|
|
||||||
|
devicePath := "/dev/foodevdir/chardevice"
|
||||||
|
mknod := SystemExec("mknod", []string{devicePath, "c", "3", "1"})
|
||||||
|
mknod.WaitWithDefaultTimeout()
|
||||||
|
Expect(mknod).Should(Exit(0))
|
||||||
|
|
||||||
|
charVolume := getHostPathVolume("BlockDevice", devicePath)
|
||||||
|
|
||||||
|
pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false))))
|
||||||
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(125))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman play kube reports error when we try to expose block device as char device", func() {
|
||||||
|
SkipIfRootless("It needs root access to create devices")
|
||||||
|
Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
|
||||||
|
defer os.RemoveAll("/dev/foodevdir")
|
||||||
|
|
||||||
|
devicePath := "/dev/foodevdir/blockdevice"
|
||||||
|
mknod := SystemExec("mknod", []string{devicePath, "b", "7", "0"})
|
||||||
|
mknod.WaitWithDefaultTimeout()
|
||||||
|
Expect(mknod).Should(Exit(0))
|
||||||
|
|
||||||
|
charVolume := getHostPathVolume("CharDevice", devicePath)
|
||||||
|
|
||||||
|
pod := getPod(withVolume(charVolume), withCtr(getCtr(withImage(registry), withCmd(nil), withArg(nil), withVolumeMount(devicePath, false))))
|
||||||
|
err = generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(125))
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user