diff --git a/pkg/apis/container.go b/pkg/apis/container.go index 9355a8ad0b..a9c6875bfd 100644 --- a/pkg/apis/container.go +++ b/pkg/apis/container.go @@ -272,6 +272,22 @@ type ContainerVolumeMountDiskPostImageOverlay struct { PathMap map[string]string `json:"path_map"` // 宿主机底层目录映射, key 为 PathMap 的 key,value 为 overlay lower 格式,多目录以 ":" 分隔 HostLowerMap map[string]*HostLowerPath `json:"host_lower_map"` + UpperConfig *PostOverlayUpperConfig `json:"upper_config"` +} + +type PostOverlayUpperConfigType string + +const ( + PostOverlayUpperConfigTypeDisk PostOverlayUpperConfigType = "disk" +) + +type PostOverlayUpperConfigDisk struct { + SubPath string `json:"sub_path"` +} + +type PostOverlayUpperConfig struct { + Type PostOverlayUpperConfigType `json:"type"` + Disk *PostOverlayUpperConfigDisk `json:"disk"` } type ContainerVolumeMountDiskPostImageOverlayUnpacker ContainerVolumeMountDiskPostImageOverlay @@ -285,6 +301,7 @@ func (ov *ContainerVolumeMountDiskPostImageOverlay) UnmarshalJSON(data []byte) e // 防止 PathMap 被合并,总是用 Unarmshal data 里面的 path_map ov.PathMap = nov.PathMap ov.HostLowerMap = nov.HostLowerMap + ov.UpperConfig = nov.UpperConfig return nil } @@ -298,6 +315,8 @@ const ( type ContainerVolumeMountDiskPostOverlay struct { // 宿主机底层目录 HostLowerDir []string `json:"host_lower_dir"` + // 宿主机上层目录 + HostUpperDir string `json:"host_upper_dir"` // 合并后要挂载到容器的目录 ContainerTargetDir string `json:"container_target_dir"` Image *ContainerVolumeMountDiskPostImageOverlay `json:"image"` diff --git a/pkg/hostman/container/volume_mount/disk/disk.go b/pkg/hostman/container/volume_mount/disk/disk.go index 3bbe2c228b..d8d7cf7e97 100644 --- a/pkg/hostman/container/volume_mount/disk/disk.go +++ b/pkg/hostman/container/volume_mount/disk/disk.go @@ -50,7 +50,7 @@ type IVolumeMountDisk interface { GetHostDiskRootPath(pod volume_mount.IPodInfo, vm *hostapi.ContainerVolumeMount) (string, error) GetPostOverlayRootWorkDir(pod volume_mount.IPodInfo, vm *hostapi.ContainerVolumeMount, ctrId string) (string, error) - GetPostOverlayRootUpperDir(pod volume_mount.IPodInfo, vm *hostapi.ContainerVolumeMount, ctrId string) (string, error) + GetPostOverlayRootUpperDir(pod volume_mount.IPodInfo, vm *hostapi.ContainerVolumeMount, ctrId string, pov *apis.ContainerVolumeMountDiskPostOverlay) (string, error) } type disk struct { diff --git a/pkg/hostman/container/volume_mount/disk/post_overlay.go b/pkg/hostman/container/volume_mount/disk/post_overlay.go index 6fe6fe82b5..730ce45e31 100644 --- a/pkg/hostman/container/volume_mount/disk/post_overlay.go +++ b/pkg/hostman/container/volume_mount/disk/post_overlay.go @@ -60,7 +60,19 @@ func (d disk) GetPostOverlayRootWorkDir(pod volume_mount.IPodInfo, vm *hostapi.C return d.getPostOverlayRootPrefixDir(POST_OVERLAY_PREFIX_WORK_DIR, pod, vm, ctrId) } -func (d disk) GetPostOverlayRootUpperDir(pod volume_mount.IPodInfo, vm *hostapi.ContainerVolumeMount, ctrId string) (string, error) { +func (d disk) GetPostOverlayRootUpperDir(pod volume_mount.IPodInfo, vm *hostapi.ContainerVolumeMount, ctrId string, pov *apis.ContainerVolumeMountDiskPostOverlay) (string, error) { + if pov.Image != nil && pov.Image.UpperConfig != nil { + config := pov.Image.UpperConfig + if config.Disk.SubPath == "" { + return "", errors.Errorf("sub_path of upper config is empty") + } + hostPath, err := d.GetHostDiskRootPath(pod, vm) + if err != nil { + return "", errors.Wrap(err, "get host disk root path") + } + upperDir := filepath.Join(hostPath, vm.Disk.SubDirectory, config.Disk.SubPath) + return upperDir, nil + } return d.getPostOverlayRootPrefixDir(POST_OVERLAY_PREFIX_UPPER_DIR, pod, vm, ctrId) } @@ -188,6 +200,9 @@ func (d diskPostOverlay) getPostOverlayUpperDir( ov *apis.ContainerVolumeMountDiskPostOverlay, ensure bool, ) (string, error) { + if ov.HostUpperDir != "" { + return ov.HostUpperDir, nil + } return d.getPostOverlayDirWithPrefix(POST_OVERLAY_PREFIX_UPPER_DIR, pod, ctrId, vm, ov, ensure) } diff --git a/pkg/hostman/container/volume_mount/disk/post_overlay_image.go b/pkg/hostman/container/volume_mount/disk/post_overlay_image.go index 8a7d16953b..5c9854bf03 100644 --- a/pkg/hostman/container/volume_mount/disk/post_overlay_image.go +++ b/pkg/hostman/container/volume_mount/disk/post_overlay_image.go @@ -78,7 +78,7 @@ func parseColonSeparatedPaths(pathStr string) []string { return paths } -func (i postOverlayImage) convertToDiskOV(ov *apis.ContainerVolumeMountDiskPostOverlay, hostPath, ctrPath string, hostLowerPath *apis.HostLowerPath) *apis.ContainerVolumeMountDiskPostOverlay { +func (i postOverlayImage) convertToDiskOV(ov *apis.ContainerVolumeMountDiskPostOverlay, hostPath, ctrPath string, hostLowerPath *apis.HostLowerPath, hostUpperDir string) *apis.ContainerVolumeMountDiskPostOverlay { hostLowerDir := []string{} if hostLowerPath != nil { // 添加 PrePath 中的路径 @@ -92,6 +92,7 @@ func (i postOverlayImage) convertToDiskOV(ov *apis.ContainerVolumeMountDiskPostO } return &apis.ContainerVolumeMountDiskPostOverlay{ HostLowerDir: hostLowerDir, + HostUpperDir: hostUpperDir, ContainerTargetDir: ctrPath, FsUser: ov.FsUser, FsGroup: ov.FsGroup, @@ -100,6 +101,7 @@ func (i postOverlayImage) convertToDiskOV(ov *apis.ContainerVolumeMountDiskPostO } func (i postOverlayImage) withAction( + vm *hostapi.ContainerVolumeMount, d diskPostOverlay, pod volume_mount.IPodInfo, ov *apis.ContainerVolumeMountDiskPostOverlay, af func(iDiskPostOverlayDriver, *apis.ContainerVolumeMountDiskPostOverlay) error, accquire bool) error { @@ -108,9 +110,21 @@ func (i postOverlayImage) withAction( if err != nil { return errors.Wrapf(err, "get cached image paths") } + hostUpperDir := "" + if img.UpperConfig != nil { + config := img.UpperConfig + if config.Disk.SubPath == "" { + return errors.Errorf("sub_path of upper config is empty") + } + hostPath, err := d.disk.GetHostDiskRootPath(pod, vm) + if err != nil { + return errors.Wrap(err, "get host disk root path") + } + hostUpperDir = filepath.Join(hostPath, vm.Disk.SubDirectory, config.Disk.SubPath) + } for hostPath, ctrPath := range paths { hostLowerPath := hostLowerPaths[hostPath] - dov := i.convertToDiskOV(ov, hostPath, ctrPath, hostLowerPath) + dov := i.convertToDiskOV(ov, hostPath, ctrPath, hostLowerPath, hostUpperDir) drv := d.getDriver(dov) if err := af(drv, dov); err != nil { return errors.Wrapf(err, "host path %s to %s", hostPath, ctrPath) @@ -120,14 +134,14 @@ func (i postOverlayImage) withAction( } func (i postOverlayImage) Mount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) error { - return i.withAction(d, pod, ov, + return i.withAction(vm, d, pod, ov, func(driver iDiskPostOverlayDriver, dov *apis.ContainerVolumeMountDiskPostOverlay) error { return driver.Mount(d, pod, ctrId, vm, dov) }, true) } func (i postOverlayImage) Unmount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, useLazy bool, clearLayers bool) error { - return i.withAction(d, pod, ov, + return i.withAction(vm, d, pod, ov, func(driver iDiskPostOverlayDriver, dov *apis.ContainerVolumeMountDiskPostOverlay) error { return driver.Unmount(d, pod, ctrId, vm, dov, useLazy, clearLayers) }, false) diff --git a/pkg/hostman/guestman/pod.go b/pkg/hostman/guestman/pod.go index 225356ea93..c6c2f5c777 100644 --- a/pkg/hostman/guestman/pod.go +++ b/pkg/hostman/guestman/pod.go @@ -2827,7 +2827,7 @@ func (s *sPodGuestInstance) DoSnapshot(ctx context.Context, params *SDiskSnapsho diskDrv := drv.(disk.IVolumeMountDisk) for _, pov := range vol.Disk.PostOverlay { // bind mount post overlay dirs to tmpBackRootDir - upperDir, err := diskDrv.GetPostOverlayRootUpperDir(s, vol, input.ContainerId) + upperDir, err := diskDrv.GetPostOverlayRootUpperDir(s, vol, input.ContainerId, pov) if err != nil { return nil, errors.Wrapf(err, "get post overlay root upper dir: %s", jsonutils.Marshal(pov)) }