post_overlay_image.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package disk
  15. import (
  16. "context"
  17. "path/filepath"
  18. "strings"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/onecloud/pkg/apis"
  21. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  22. "yunion.io/x/onecloud/pkg/hostman/container/volume_mount"
  23. fileutils "yunion.io/x/onecloud/pkg/util/fileutils2"
  24. )
  25. func init() {
  26. registerPostOverlayDriver(newPostOverlayImage())
  27. }
  28. func newPostOverlayImage() iDiskPostOverlayDriver {
  29. return &postOverlayImage{}
  30. }
  31. type postOverlayImage struct {
  32. }
  33. func (i postOverlayImage) GetType() apis.ContainerVolumeMountDiskPostOverlayType {
  34. return apis.CONTAINER_VOLUME_MOUNT_DISK_POST_OVERLAY_IMAGE
  35. }
  36. func (i postOverlayImage) getImageInput(ov *apis.ContainerVolumeMountDiskPostOverlay) *apis.ContainerVolumeMountDiskPostImageOverlay {
  37. return ov.Image
  38. }
  39. func (i postOverlayImage) getCachedImagePaths(d diskPostOverlay, pod volume_mount.IPodInfo, img *apis.ContainerVolumeMountDiskPostImageOverlay, accquire bool) (map[string]string, map[string]*apis.HostLowerPath, error) {
  40. cachedImgDir, err := d.disk.getCachedImageDir(context.Background(), pod, img.Id, accquire)
  41. if err != nil {
  42. return nil, nil, errors.Wrap(err, "disk.getCachedImageDir")
  43. }
  44. hostLowerMap := make(map[string]*apis.HostLowerPath)
  45. if img.HostLowerMap != nil {
  46. hostLowerMap = img.HostLowerMap
  47. }
  48. result := make(map[string]string)
  49. lowerResult := make(map[string]*apis.HostLowerPath)
  50. for hostPathSuffix, ctrPath := range img.PathMap {
  51. hostPath := filepath.Join(cachedImgDir, hostPathSuffix)
  52. result[hostPath] = ctrPath
  53. hostLowerPath := hostLowerMap[hostPathSuffix]
  54. if hostLowerPath != nil {
  55. lowerResult[hostPath] = hostLowerPath
  56. }
  57. }
  58. return result, lowerResult, nil
  59. }
  60. // parseColonSeparatedPaths 解析冒号分隔的路径字符串,过滤空字符串并返回路径列表
  61. func parseColonSeparatedPaths(pathStr string) []string {
  62. var paths []string
  63. for _, path := range strings.Split(pathStr, ":") {
  64. if path != "" {
  65. paths = append(paths, path)
  66. }
  67. }
  68. return paths
  69. }
  70. func (i postOverlayImage) convertToDiskOV(ov *apis.ContainerVolumeMountDiskPostOverlay, hostPath, ctrPath string, hostLowerPath *apis.HostLowerPath, hostUpperDir string) *apis.ContainerVolumeMountDiskPostOverlay {
  71. hostLowerDir := []string{}
  72. if hostLowerPath != nil {
  73. // 添加 PrePath 中的路径
  74. hostLowerDir = append(hostLowerDir, parseColonSeparatedPaths(hostLowerPath.PrePath)...)
  75. }
  76. // 添加当前 hostPath
  77. hostLowerDir = append(hostLowerDir, hostPath)
  78. if hostLowerPath != nil {
  79. // 添加 PostPath 中的路径
  80. hostLowerDir = append(hostLowerDir, parseColonSeparatedPaths(hostLowerPath.PostPath)...)
  81. }
  82. return &apis.ContainerVolumeMountDiskPostOverlay{
  83. HostLowerDir: hostLowerDir,
  84. HostUpperDir: hostUpperDir,
  85. ContainerTargetDir: ctrPath,
  86. FsUser: ov.FsUser,
  87. FsGroup: ov.FsGroup,
  88. FlattenLayers: ov.FlattenLayers,
  89. }
  90. }
  91. func (i postOverlayImage) withAction(
  92. vm *hostapi.ContainerVolumeMount,
  93. d diskPostOverlay, pod volume_mount.IPodInfo, ov *apis.ContainerVolumeMountDiskPostOverlay,
  94. af func(iDiskPostOverlayDriver, *apis.ContainerVolumeMountDiskPostOverlay) error,
  95. accquire bool) error {
  96. img := i.getImageInput(ov)
  97. paths, hostLowerPaths, err := i.getCachedImagePaths(d, pod, img, accquire)
  98. if err != nil {
  99. return errors.Wrapf(err, "get cached image paths")
  100. }
  101. hostUpperDir := ""
  102. if img.UpperConfig != nil {
  103. config := img.UpperConfig
  104. if config.Disk.SubPath == "" {
  105. return errors.Errorf("sub_path of upper config is empty")
  106. }
  107. hostPath, err := d.disk.GetHostDiskRootPath(pod, vm)
  108. if err != nil {
  109. return errors.Wrap(err, "get host disk root path")
  110. }
  111. hostUpperDir = filepath.Join(hostPath, vm.Disk.SubDirectory, config.Disk.SubPath)
  112. if !fileutils.Exists(hostUpperDir) {
  113. if err := volume_mount.EnsureDir(hostUpperDir); err != nil {
  114. return errors.Wrapf(err, "ensure dir %s", hostUpperDir)
  115. }
  116. }
  117. }
  118. for hostPath, ctrPath := range paths {
  119. hostLowerPath := hostLowerPaths[hostPath]
  120. dov := i.convertToDiskOV(ov, hostPath, ctrPath, hostLowerPath, hostUpperDir)
  121. drv := d.getDriver(dov)
  122. if err := af(drv, dov); err != nil {
  123. return errors.Wrapf(err, "host path %s to %s", hostPath, ctrPath)
  124. }
  125. }
  126. return nil
  127. }
  128. func (i postOverlayImage) Mount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay) error {
  129. return i.withAction(vm, d, pod, ov,
  130. func(driver iDiskPostOverlayDriver, dov *apis.ContainerVolumeMountDiskPostOverlay) error {
  131. return driver.Mount(d, pod, ctrId, vm, dov)
  132. }, true)
  133. }
  134. func (i postOverlayImage) Unmount(d diskPostOverlay, pod volume_mount.IPodInfo, ctrId string, vm *hostapi.ContainerVolumeMount, ov *apis.ContainerVolumeMountDiskPostOverlay, useLazy bool, clearLayers bool) error {
  135. return i.withAction(vm, d, pod, ov,
  136. func(driver iDiskPostOverlayDriver, dov *apis.ContainerVolumeMountDiskPostOverlay) error {
  137. return driver.Unmount(d, pod, ctrId, vm, dov, useLazy, clearLayers)
  138. }, false)
  139. }