github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/filesystem/cloudfilesystem/overlay2.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 cloudfilesystem 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 "sync" 22 23 "github.com/alibaba/sealer/utils" 24 25 "github.com/alibaba/sealer/utils/platform" 26 27 "github.com/alibaba/sealer/common" 28 "github.com/alibaba/sealer/pkg/env" 29 "github.com/alibaba/sealer/pkg/runtime" 30 v2 "github.com/alibaba/sealer/types/api/v2" 31 "github.com/alibaba/sealer/utils/ssh" 32 "golang.org/x/sync/errgroup" 33 ) 34 35 const ( 36 RemoteChmod = "cd %s && chmod +x scripts/* && cd scripts && bash init.sh /var/lib/docker %s %s" 37 ) 38 39 type overlayFileSystem struct { 40 } 41 42 func (o *overlayFileSystem) MountRootfs(cluster *v2.Cluster, hosts []string, initFlag bool) error { 43 clusterRootfsDir := common.DefaultTheClusterRootfsDir(cluster.Name) 44 //scp roofs to all Masters and Nodes,then do init.sh 45 if err := mountRootfs(hosts, clusterRootfsDir, cluster, initFlag); err != nil { 46 return fmt.Errorf("mount rootfs failed %v", err) 47 } 48 return nil 49 } 50 51 func (o *overlayFileSystem) UnMountRootfs(cluster *v2.Cluster, hosts []string) error { 52 //do clean.sh,then remove all Masters and Nodes roofs 53 if err := unmountRootfs(hosts, cluster); err != nil { 54 return err 55 } 56 return nil 57 } 58 59 func mountRootfs(ipList []string, target string, cluster *v2.Cluster, initFlag bool) error { 60 clusterPlatform, err := ssh.GetClusterPlatform(cluster) 61 if err != nil { 62 return err 63 } 64 mountEntry := struct { 65 *sync.RWMutex 66 mountDirs map[string]bool 67 }{&sync.RWMutex{}, make(map[string]bool)} 68 config := runtime.GetRegistryConfig(platform.DefaultMountCloudImageDir(cluster.Name), runtime.GetMaster0Ip(cluster)) 69 eg, _ := errgroup.WithContext(context.Background()) 70 for _, IP := range ipList { 71 ip := IP 72 eg.Go(func() error { 73 src := platform.GetMountCloudImagePlatformDir(cluster.Name, clusterPlatform[ip]) 74 initCmd := fmt.Sprintf(RemoteChmod, target, config.Domain, config.Port) 75 mountEntry.Lock() 76 if !mountEntry.mountDirs[src] { 77 mountEntry.mountDirs[src] = true 78 } 79 mountEntry.Unlock() 80 sshClient, err := ssh.GetHostSSHClient(ip, cluster) 81 if err != nil { 82 return fmt.Errorf("get host ssh client failed %v", err) 83 } 84 err = copyFiles(sshClient, ip, src, target) 85 if err != nil { 86 return fmt.Errorf("copy rootfs failed %v", err) 87 } 88 if initFlag { 89 err = sshClient.CmdAsync(ip, env.NewEnvProcessor(cluster).WrapperShell(ip, initCmd)) 90 if err != nil { 91 return fmt.Errorf("exec init.sh failed %v", err) 92 } 93 } 94 return err 95 }) 96 } 97 if err = eg.Wait(); err != nil { 98 return err 99 } 100 // if config.ip is not in mountRootfs ipList, mean copy registry dir is not required, like scale up node 101 if !utils.InList(config.IP, ipList) { 102 return nil 103 } 104 return copyRegistry(config.IP, cluster, mountEntry.mountDirs, target) 105 } 106 107 func unmountRootfs(ipList []string, cluster *v2.Cluster) error { 108 var ( 109 clusterRootfsDir = common.DefaultTheClusterRootfsDir(cluster.Name) 110 cleanFile = fmt.Sprintf(common.DefaultClusterClearBashFile, cluster.Name) 111 unmount = fmt.Sprintf("(! mountpoint -q %[1]s || umount -lf %[1]s)", clusterRootfsDir) 112 execClean = fmt.Sprintf("if [ -f \"%[1]s\" ];then chmod +x %[1]s && /bin/bash -c %[1]s;fi", cleanFile) 113 rmRootfs = fmt.Sprintf("rm -rf %s", clusterRootfsDir) 114 envProcessor = env.NewEnvProcessor(cluster) 115 cmd = strings.Join([]string{execClean, unmount, rmRootfs}, " && ") 116 ) 117 118 eg, _ := errgroup.WithContext(context.Background()) 119 for _, IP := range ipList { 120 ip := IP 121 eg.Go(func() error { 122 SSH, err := ssh.GetHostSSHClient(ip, cluster) 123 if err != nil { 124 return err 125 } 126 127 return SSH.CmdAsync(ip, envProcessor.WrapperShell(ip, cmd)) 128 }) 129 } 130 return eg.Wait() 131 } 132 133 func NewOverlayFileSystem() (Interface, error) { 134 return &overlayFileSystem{}, nil 135 }