github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/imagedistributor/mount.go (about) 1 // Copyright © 2022 Alibaba Group Holding Ltd. 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 15 package imagedistributor 16 17 import ( 18 "fmt" 19 "net" 20 "os" 21 "path/filepath" 22 "strings" 23 24 "github.com/sealerio/sealer/pkg/define/options" 25 "github.com/sealerio/sealer/pkg/imageengine" 26 v1 "github.com/sealerio/sealer/types/api/v1" 27 "github.com/sealerio/sealer/utils/os/fs" 28 ) 29 30 type buildAhMounter struct { 31 imageEngine imageengine.Interface 32 } 33 34 func (b buildAhMounter) Mount(imageName string, platform v1.Platform, dest string) (string, string, string, error) { 35 mountDir := filepath.Join(dest, 36 strings.ReplaceAll(imageName, "/", "_"), 37 strings.Join([]string{platform.OS, platform.Architecture, platform.Variant}, "_")) 38 39 imageID, err := b.imageEngine.Pull(&options.PullOptions{ 40 Quiet: false, 41 PullPolicy: "missing", 42 Image: imageName, 43 Platform: platform.ToString(), 44 }) 45 if err != nil { 46 return "", "", "", err 47 } 48 49 if err := fs.FS.MkdirAll(filepath.Dir(mountDir)); err != nil { 50 return "", "", "", err 51 } 52 53 id, err := b.imageEngine.CreateWorkingContainer(&options.BuildRootfsOptions{ 54 DestDir: mountDir, 55 ImageNameOrID: imageID, 56 }) 57 58 if err != nil { 59 return "", "", "", err 60 } 61 return mountDir, id, imageID, nil 62 } 63 64 func (b buildAhMounter) Umount(mountDir, cid string) error { 65 if err := fs.FS.RemoveAll(mountDir); err != nil { 66 return fmt.Errorf("failed to remove mount dir %s: %v", mountDir, err) 67 } 68 69 if err := b.imageEngine.RemoveContainer(&options.RemoveContainerOptions{ 70 ContainerNamesOrIDs: []string{cid}, 71 }); err != nil { 72 return fmt.Errorf("failed to remove working container: %v", err) 73 } 74 75 return nil 76 } 77 78 func NewBuildAhMounter(imageEngine imageengine.Interface) Mounter { 79 return buildAhMounter{ 80 imageEngine: imageEngine, 81 } 82 } 83 84 type ImagerMounter struct { 85 Mounter 86 rootDir string 87 hostsPlatform map[v1.Platform][]net.IP 88 } 89 90 type ClusterImageMountInfo struct { 91 // target hosts ip list, not all cluster ips. 92 Hosts []net.IP 93 Platform v1.Platform 94 MountDir string 95 ContainerID string 96 ImageID string 97 } 98 99 func (c ImagerMounter) Mount(imageName string) ([]ClusterImageMountInfo, error) { 100 var imageMountInfos []ClusterImageMountInfo 101 for platform, hosts := range c.hostsPlatform { 102 mountDir, cid, imageID, err := c.Mounter.Mount(imageName, platform, c.rootDir) 103 if err != nil { 104 return nil, fmt.Errorf("failed to mount image %s with platform %s:%v", imageName, platform.ToString(), err) 105 } 106 imageMountInfos = append(imageMountInfos, ClusterImageMountInfo{ 107 Hosts: hosts, 108 Platform: platform, 109 MountDir: mountDir, 110 ContainerID: cid, 111 ImageID: imageID, 112 }) 113 } 114 115 return imageMountInfos, nil 116 } 117 118 func (c ImagerMounter) Umount(imageName string, imageMountInfo []ClusterImageMountInfo) error { 119 for _, info := range imageMountInfo { 120 err := c.Mounter.Umount(info.MountDir, info.ContainerID) 121 if err != nil { 122 return fmt.Errorf("failed to umount %s:%v", info.MountDir, err) 123 } 124 } 125 126 // delete all mounted images 127 if err := fs.FS.RemoveAll(c.rootDir); err != nil { 128 return err 129 } 130 return nil 131 } 132 133 func NewImageMounter(imageEngine imageengine.Interface, hostsPlatform map[v1.Platform][]net.IP) (*ImagerMounter, error) { 134 tempDir, err := os.MkdirTemp("", "sealer-mount-tmp") 135 if err != nil { 136 return nil, fmt.Errorf("failed to create tmp mount dir, err: %v", err) 137 } 138 139 c := &ImagerMounter{ 140 // todo : user could set this value by env or sealer config 141 rootDir: tempDir, 142 hostsPlatform: hostsPlatform, 143 } 144 145 c.Mounter = NewBuildAhMounter(imageEngine) 146 return c, nil 147 }