mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-31 02:38:07 +08:00
feat(host): support single file to use post overlay (#23159)
This commit is contained in:
@@ -26,8 +26,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
POST_OVERLAY_PREFIX_WORK_DIR = "_post_overlay_work_"
|
||||
POST_OVERLAY_PREFIX_UPPER_DIR = "_post_overlay_upper_"
|
||||
POST_OVERLAY_PREFIX_LOWER_DIR = "_post_overlay_lower_"
|
||||
POST_OVERLAY_PREFIX_WORK_DIR = "_post_overlay_work_"
|
||||
POST_OVERLAY_PREFIX_UPPER_DIR = "_post_overlay_upper_"
|
||||
POST_OVERLAY_PREFIX_MERGED_DIR = "_post_overlay_merged_"
|
||||
)
|
||||
|
||||
func (d disk) MountPostOverlays(pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ovs []*apis.ContainerVolumeMountDiskPostOverlay) error {
|
||||
@@ -128,7 +130,7 @@ func (d diskPostOverlay) getPostOverlayDirWithPrefix(
|
||||
workDir := filepath.Join(rootPath, ov.ContainerTargetDir)
|
||||
if ensure {
|
||||
if err := volume_mount.EnsureDir(workDir); err != nil {
|
||||
return "", errors.Wrapf(err, "make %s", workDir)
|
||||
return "", errors.Wrapf(err, "makeDir %s", workDir)
|
||||
}
|
||||
}
|
||||
return workDir, nil
|
||||
@@ -152,7 +154,20 @@ func (d diskPostOverlay) getPostOverlayUpperDir(
|
||||
return d.getPostOverlayDirWithPrefix(POST_OVERLAY_PREFIX_UPPER_DIR, pod, ctrId, vm, ov, ensure)
|
||||
}
|
||||
|
||||
func (d diskPostOverlay) getPostOverlayMountpoint(pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) (string, error) {
|
||||
func (d diskPostOverlay) getPostOverlayLowerDir(
|
||||
pod volume_mount.IPodInfo, ctrId string,
|
||||
vm *hostapi.ContainerVolumeMount,
|
||||
ov *apis.ContainerVolumeMountDiskPostOverlay,
|
||||
ensure bool,
|
||||
) (string, error) {
|
||||
return d.getPostOverlayDirWithPrefix(POST_OVERLAY_PREFIX_LOWER_DIR, pod, ctrId, vm, ov, ensure)
|
||||
}
|
||||
|
||||
func (d diskPostOverlay) getPostOverlayMergedDir(pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, ensure bool) (string, error) {
|
||||
return d.getPostOverlayDirWithPrefix(POST_OVERLAY_PREFIX_MERGED_DIR, pod, ctrId, vm, ov, ensure)
|
||||
}
|
||||
|
||||
func (d diskPostOverlay) getPostOverlayMountpoint(pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, ensure bool) (string, error) {
|
||||
ctrMountHostPath, err := d.disk.GetRuntimeMountHostPath(pod, ctrId, vm)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "get runtime mount host_path")
|
||||
@@ -160,8 +175,10 @@ func (d diskPostOverlay) getPostOverlayMountpoint(pod volume_mount.IPodInfo, ctr
|
||||
// remove hostPath sub_directory path
|
||||
ctrMountHostPath = strings.TrimSuffix(ctrMountHostPath, vm.Disk.SubDirectory)
|
||||
mergedDir := filepath.Join(ctrMountHostPath, ov.ContainerTargetDir)
|
||||
if err := volume_mount.EnsureDir(mergedDir); err != nil {
|
||||
return "", errors.Wrap(err, "make merged mountpoint dir")
|
||||
if ensure {
|
||||
if err := volume_mount.EnsureDir(mergedDir); err != nil {
|
||||
return "", errors.Wrap(err, "make merged mountpoint dir")
|
||||
}
|
||||
}
|
||||
return mergedDir, nil
|
||||
}
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/container/volume_mount"
|
||||
fileutils "yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/mountutils"
|
||||
)
|
||||
|
||||
@@ -38,7 +41,14 @@ func (p postOverlayHostPath) GetType() apis.ContainerVolumeMountDiskPostOverlayT
|
||||
return apis.CONTAINER_VOLUME_MOUNT_DISK_POST_OVERLAY_HOSTPATH
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) Mount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) error {
|
||||
func (p postOverlayHostPath) getSingleFilePath(ov *apis.ContainerVolumeMountDiskPostOverlay) string {
|
||||
if len(ov.HostLowerDir) == 1 && fileutils.IsFile(ov.HostLowerDir[0]) {
|
||||
return ov.HostLowerDir[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) mountDir(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) error {
|
||||
upperDir, err := d.getPostOverlayUpperDir(pod, ctrId, vm, ov, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay upper dir for container %s", ctrId)
|
||||
@@ -49,7 +59,7 @@ func (p postOverlayHostPath) Mount(d diskPostOverlay, pod volume_mount.IPodInfo,
|
||||
return errors.Wrapf(err, "get post overlay work dir for container %s", ctrId)
|
||||
}
|
||||
|
||||
mergedDir, err := d.getPostOverlayMountpoint(pod, ctrId, vm, ov)
|
||||
mergedDir, err := d.getPostOverlayMountpoint(pod, ctrId, vm, ov, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay mountpoint for container %s", ctrId)
|
||||
}
|
||||
@@ -65,8 +75,72 @@ func (p postOverlayHostPath) Mount(d diskPostOverlay, pod volume_mount.IPodInfo,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) Unmount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, useLazy bool, cleanLayers bool) error {
|
||||
mergedDir, err := d.getPostOverlayMountpoint(pod, ctrId, vm, ov)
|
||||
func (p postOverlayHostPath) getSingleFileMergedFilePath(mergedDir string, singleFilePath string) string {
|
||||
return filepath.Join(mergedDir, filepath.Base(singleFilePath))
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) mountSingleFile(singleFilePath string, d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) error {
|
||||
// 如果是单文件,创建一个目录,再把该文件拷贝过去
|
||||
lowerDir, err := d.getPostOverlayLowerDir(pod, ctrId, vm, ov, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get single file lower dir for container %s", ctrId)
|
||||
}
|
||||
if err := volume_mount.CopyFile(singleFilePath, lowerDir); err != nil {
|
||||
return errors.Wrapf(err, "copy file %s to %s", singleFilePath, lowerDir)
|
||||
}
|
||||
|
||||
// 把但文件的 lowerDir 挂载到 targetMergedDir,然后在把 singleFileMergedFilePath bind mount 到 mergedDir(mergedDir 其实是个文件路径)
|
||||
upperDir, err := d.getPostOverlayUpperDir(pod, ctrId, vm, ov, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay upper dir for container %s", ctrId)
|
||||
}
|
||||
workDir, err := d.getPostOverlayWorkDir(pod, ctrId, vm, ov, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay work dir for container %s", ctrId)
|
||||
}
|
||||
mergedDst, err := d.getPostOverlayMountpoint(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay mountpoint for container %s", ctrId)
|
||||
}
|
||||
targetMergedDir, err := d.getPostOverlayMergedDir(pod, ctrId, vm, ov, true)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay merged dir for container %s", ctrId)
|
||||
}
|
||||
if err := mountutils.MountOverlayWithFeatures([]string{lowerDir}, upperDir, workDir, targetMergedDir, &mountutils.MountOverlayFeatures{
|
||||
MetaCopy: true,
|
||||
}); err != nil {
|
||||
return errors.Wrapf(err, "mount overlay dir for container %s", ctrId)
|
||||
}
|
||||
singleFileMergedFilePath := p.getSingleFileMergedFilePath(targetMergedDir, singleFilePath)
|
||||
if err := volume_mount.ChangeDirOwnerDirectly(singleFileMergedFilePath, ov.FsUser, ov.FsGroup); err != nil {
|
||||
return errors.Wrapf(err, "change file %s owner", singleFilePath)
|
||||
}
|
||||
if !fileutils.Exists(mergedDst) {
|
||||
if err := volume_mount.TouchFile(mergedDst); err != nil {
|
||||
return errors.Wrapf(err, "touch file %s", mergedDst)
|
||||
}
|
||||
}
|
||||
if err := mountutils.MountBind(singleFileMergedFilePath, mergedDst); err != nil {
|
||||
return errors.Wrapf(err, "bind mount %s to %s", singleFileMergedFilePath, mergedDst)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) Mount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) error {
|
||||
// 支持单文件挂载
|
||||
singleFilePath := ""
|
||||
if len(ov.HostLowerDir) == 1 && fileutils.IsFile(ov.HostLowerDir[0]) {
|
||||
singleFilePath = ov.HostLowerDir[0]
|
||||
}
|
||||
if singleFilePath != "" {
|
||||
return p.mountSingleFile(singleFilePath, d, pod, ctrId, vm, ov)
|
||||
} else {
|
||||
return p.mountDir(d, pod, ctrId, vm, ov)
|
||||
}
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) unmountDir(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, useLazy bool, cleanLayers bool) error {
|
||||
mergedDir, err := d.getPostOverlayMountpoint(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay mountpoint for container %s", ctrId)
|
||||
}
|
||||
@@ -92,3 +166,58 @@ func (p postOverlayHostPath) Unmount(d diskPostOverlay, pod volume_mount.IPodInf
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) unmountSingleFile(singleFilePath string, d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, useLazy bool, cleanLayers bool) error {
|
||||
mergedDir, err := d.getPostOverlayMountpoint(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay mountpoint for container %s", ctrId)
|
||||
}
|
||||
targetMergedDir, err := d.getPostOverlayMergedDir(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay merged dir for container %s", ctrId)
|
||||
}
|
||||
singleFileMergedFilePath := p.getSingleFileMergedFilePath(targetMergedDir, singleFilePath)
|
||||
|
||||
// 先 unbind mergedDir
|
||||
if err := mountutils.Unmount(mergedDir, false); err != nil {
|
||||
return errors.Wrapf(err, "unmount %s of single file %s", mergedDir, singleFileMergedFilePath)
|
||||
}
|
||||
|
||||
if err := mountutils.Unmount(targetMergedDir, useLazy); err != nil {
|
||||
return errors.Wrapf(err, "unmount %s", targetMergedDir)
|
||||
}
|
||||
if cleanLayers {
|
||||
upperDir, err := d.getPostOverlayUpperDir(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay upper dir for container %s", ctrId)
|
||||
}
|
||||
workDir, err := d.getPostOverlayWorkDir(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay work dir for container %s", ctrId)
|
||||
}
|
||||
lowerDir, err := d.getPostOverlayLowerDir(pod, ctrId, vm, ov, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get post overlay lower dir for container %s", ctrId)
|
||||
}
|
||||
|
||||
for _, dir := range []string{upperDir, workDir, lowerDir, targetMergedDir} {
|
||||
if err := volume_mount.RemoveDir(dir); err != nil {
|
||||
return errors.Wrapf(err, "remove dir %s", dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p postOverlayHostPath) Unmount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, useLazy bool, cleanLayers bool) error {
|
||||
// 支持单文件卸载
|
||||
singleFilePath := ""
|
||||
if len(ov.HostLowerDir) == 1 && fileutils.IsFile(ov.HostLowerDir[0]) {
|
||||
singleFilePath = ov.HostLowerDir[0]
|
||||
}
|
||||
if singleFilePath != "" {
|
||||
return p.unmountSingleFile(singleFilePath, d, pod, ctrId, vm, ov, useLazy, cleanLayers)
|
||||
} else {
|
||||
return p.unmountDir(d, pod, ctrId, vm, ov, useLazy, cleanLayers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,14 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
)
|
||||
|
||||
func TouchFile(file string) error {
|
||||
out, err := procutils.NewRemoteCommandAsFarAsPossible("touch", file).Output()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "touch %s: %s", file, out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func EnsureDir(dir string) error {
|
||||
out, err := procutils.NewRemoteCommandAsFarAsPossible("mkdir", "-p", dir).Output()
|
||||
if err != nil {
|
||||
@@ -63,7 +71,15 @@ func ChangeDirOwnerDirectly(hostPath string, fsUser, fsGroup *int64) error {
|
||||
}
|
||||
out, err := procutils.NewRemoteCommandAsFarAsPossible("chown", args, hostPath).Output()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "chown -R %s %s: %s", args, hostPath, string(out))
|
||||
return errors.Wrapf(err, "chown %s %s: %s", args, hostPath, string(out))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CopyFile(src, dst string) error {
|
||||
out, err := procutils.NewRemoteCommandAsFarAsPossible("cp", src, dst).Output()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cp %s %s: %s", src, dst, string(out))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user