github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/filesystem/cloudimage/cloudimage.go (about) 1 // Copyright © 2021 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 cloudimage 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "time" 23 24 "github.com/alibaba/sealer/pkg/env" 25 26 "github.com/alibaba/sealer/utils/platform" 27 28 "github.com/alibaba/sealer/common" 29 "github.com/alibaba/sealer/pkg/image" 30 "github.com/alibaba/sealer/pkg/image/store" 31 v2 "github.com/alibaba/sealer/types/api/v2" 32 "github.com/alibaba/sealer/utils" 33 "github.com/alibaba/sealer/utils/mount" 34 "github.com/alibaba/sealer/utils/ssh" 35 ) 36 37 type Interface interface { 38 MountImage(cluster *v2.Cluster) error 39 UnMountImage(cluster *v2.Cluster) error 40 } 41 42 type mounter struct { 43 imageStore store.ImageStore 44 } 45 46 func (m *mounter) MountImage(cluster *v2.Cluster) error { 47 return m.mountImage(cluster) 48 } 49 50 func (m *mounter) UnMountImage(cluster *v2.Cluster) error { 51 return m.umountImage(cluster) 52 } 53 54 func (m *mounter) umountImage(cluster *v2.Cluster) error { 55 mountRootDir := filepath.Join(common.DefaultClusterRootfsDir, cluster.Name, "mount") 56 if !utils.IsFileExist(mountRootDir) { 57 return nil 58 } 59 dir, err := ioutil.ReadDir(mountRootDir) 60 if err != nil { 61 return err 62 } 63 for _, f := range dir { 64 if !f.IsDir() { 65 continue 66 } 67 if isMount, _ := mount.GetMountDetails(filepath.Join(mountRootDir, f.Name())); isMount { 68 err := utils.Retry(10, time.Second, func() error { 69 return mount.NewMountDriver().Unmount(filepath.Join(mountRootDir, f.Name())) 70 }) 71 if err != nil { 72 return fmt.Errorf("failed to unmount dir %s,err: %v", filepath.Join(mountRootDir, f.Name()), err) 73 } 74 } 75 } 76 return os.RemoveAll(mountRootDir) 77 } 78 79 func (m *mounter) mountImage(cluster *v2.Cluster) error { 80 var ( 81 mountDirs = make(map[string]bool) 82 driver = mount.NewMountDriver() 83 err error 84 ) 85 clusterPlatform, err := ssh.GetClusterPlatform(cluster) 86 if err != nil { 87 return err 88 } 89 clusterPlatform["local"] = *platform.GetDefaultPlatform() 90 for _, v := range clusterPlatform { 91 pfm := v 92 mountDir := platform.GetMountCloudImagePlatformDir(cluster.Name, pfm) 93 upperDir := filepath.Join(mountDir, "upper") 94 if mountDirs[mountDir] { 95 continue 96 } 97 mountDirs[mountDir] = true 98 if isMount, _ := mount.GetMountDetails(mountDir); isMount { 99 err = driver.Unmount(mountDir) 100 if err != nil { 101 return fmt.Errorf("%s already mount, and failed to umount %v", mountDir, err) 102 } 103 } 104 if utils.IsFileExist(mountDir) { 105 if err = os.RemoveAll(mountDir); err != nil { 106 return fmt.Errorf("failed to clean %s, %v", mountDir, err) 107 } 108 } 109 Image, err := m.imageStore.GetByName(cluster.Spec.Image, &pfm) 110 if err != nil { 111 return err 112 } 113 layers, err := image.GetImageLayerDirs(Image) 114 if err != nil { 115 return fmt.Errorf("get layers failed: %v", err) 116 } 117 118 if err = os.MkdirAll(upperDir, common.FileMode0755); err != nil { 119 return fmt.Errorf("create upperdir failed, %s", err) 120 } 121 if err = driver.Mount(mountDir, upperDir, layers...); err != nil { 122 return fmt.Errorf("mount files failed %v", err) 123 } 124 // use env list to render image mount dir: etc,charts,manifests. 125 err = renderENV(mountDir, cluster.GetAllIPList(), env.NewEnvProcessor(cluster)) 126 if err != nil { 127 return err 128 } 129 } 130 return nil 131 } 132 133 func renderENV(imageMountDir string, ipList []string, p env.Interface) error { 134 var ( 135 renderEtc = filepath.Join(imageMountDir, common.EtcDir) 136 renderChart = filepath.Join(imageMountDir, common.RenderChartsDir) 137 renderManifests = filepath.Join(imageMountDir, common.RenderManifestsDir) 138 ) 139 140 for _, ip := range ipList { 141 for _, dir := range []string{renderEtc, renderChart, renderManifests} { 142 if utils.IsExist(dir) { 143 err := p.RenderAll(ip, dir) 144 if err != nil { 145 return err 146 } 147 } 148 } 149 } 150 return nil 151 } 152 153 func NewCloudImageMounter(is store.ImageStore) (Interface, error) { 154 return &mounter{ 155 imageStore: is, 156 }, nil 157 }