github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/filesystem/cloudfilesystem/nydus.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  	"path/filepath"
    21  
    22  	"github.com/alibaba/sealer/utils/platform"
    23  
    24  	"golang.org/x/sync/errgroup"
    25  
    26  	"github.com/alibaba/sealer/logger"
    27  	"github.com/alibaba/sealer/pkg/env"
    28  
    29  	"github.com/alibaba/sealer/pkg/runtime"
    30  	v2 "github.com/alibaba/sealer/types/api/v2"
    31  
    32  	"github.com/alibaba/sealer/common"
    33  	"github.com/alibaba/sealer/utils"
    34  	"github.com/alibaba/sealer/utils/ssh"
    35  )
    36  
    37  const (
    38  	RemoteNydusdInit = "cd %s && chmod +x *.sh && bash start.sh %s"
    39  	RemoteNydusdStop = "if [ -f \"%[1]s\" ];then sh %[1]s;fi && rm -rf %s"
    40  )
    41  
    42  type nydusFileSystem struct {
    43  }
    44  
    45  func (n *nydusFileSystem) MountRootfs(cluster *v2.Cluster, hosts []string, initFlag bool) error {
    46  	clusterRootfsDir := common.DefaultTheClusterRootfsDir(cluster.Name)
    47  	//scp roofs to all Masters and Nodes,then do init.sh
    48  	if err := mountNydusRootfs(hosts, clusterRootfsDir, cluster, initFlag); err != nil {
    49  		return fmt.Errorf("mount rootfs failed %v", err)
    50  	}
    51  
    52  	return nil
    53  }
    54  
    55  func (n *nydusFileSystem) UnMountRootfs(cluster *v2.Cluster, hosts []string) error {
    56  	var (
    57  		nydusdFileDir     = common.DefaultTheClusterNydusdFileDir(cluster.Name)
    58  		nydusdServerClean = filepath.Join(nydusdFileDir, "serverfile", "serverclean.sh")
    59  	)
    60  	//do clean.sh,then remove all Masters and Nodes roofs
    61  	if err := unmountRootfs(hosts, cluster); err != nil {
    62  		return err
    63  	}
    64  
    65  	if utils.IsExist(nydusdServerClean) {
    66  		cleanCmd := fmt.Sprintf("sh %s", nydusdServerClean)
    67  		_, err := utils.RunSimpleCmd(cleanCmd)
    68  		if err != nil {
    69  			return fmt.Errorf("failed to stop nydusdserver %v", err)
    70  		}
    71  	} else {
    72  		logger.Info("%s not found", nydusdServerClean)
    73  	}
    74  	return nil
    75  }
    76  
    77  func mountNydusRootfs(ipList []string, target string, cluster *v2.Cluster, initFlag bool) error {
    78  	clusterPlatform, err := ssh.GetClusterPlatform(cluster)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	localIP, err := utils.GetLocalIP(cluster.GetMaster0IP() + ":22")
    83  	if err != nil {
    84  		return fmt.Errorf("failed to get local address, %v", err)
    85  	}
    86  	var (
    87  		nydusdfileSrc   = filepath.Join(platform.DefaultMountCloudImageDir(cluster.Name), "nydusdfile")
    88  		nydusdFileDir   = common.DefaultTheClusterNydusdFileDir(cluster.Name)
    89  		nydusdserverDir = filepath.Join(nydusdFileDir, "serverfile")
    90  		nydusdfileCpCmd = fmt.Sprintf("rm -rf %s && cp -r %s %s", nydusdFileDir, nydusdfileSrc, nydusdFileDir)
    91  		nydusdDir       = common.DefaultTheClusterNydusdDir(cluster.Name)
    92  		nydusdInitCmd   = fmt.Sprintf(RemoteNydusdInit, nydusdDir, target)
    93  		nydusdCleanCmd  = fmt.Sprintf(RemoteNydusdStop, filepath.Join(nydusdDir, "clean.sh"), nydusdDir)
    94  		cleanCmd        = fmt.Sprintf("echo '%s' >> "+common.DefaultClusterClearBashFile, nydusdCleanCmd, cluster.Name)
    95  		envProcessor    = env.NewEnvProcessor(cluster)
    96  		config          = runtime.GetRegistryConfig(platform.DefaultMountCloudImageDir(cluster.Name), runtime.GetMaster0Ip(cluster))
    97  		initCmd         = fmt.Sprintf(RemoteChmod, target, config.Domain, config.Port)
    98  	)
    99  	_, err = utils.RunSimpleCmd(nydusdfileCpCmd)
   100  	if err != nil {
   101  		return fmt.Errorf("cp nydusdfile failed %v", err)
   102  	}
   103  	//dirs need be converted
   104  	mountDirs := make(map[string]bool)
   105  	dirlist := ""
   106  	for _, IP := range ipList {
   107  		ip := IP
   108  		src := platform.GetMountCloudImagePlatformDir(cluster.Name, clusterPlatform[ip])
   109  		if !mountDirs[src] {
   110  			mountDirs[src] = true
   111  			dirlist = dirlist + fmt.Sprintf(",%s", src)
   112  			clientfileSrc := filepath.Join(src, "nydusdfile", "clientfile")
   113  			clientfileDest := filepath.Join(nydusdFileDir, filepath.Base(src))
   114  			nydusdCpCmd := fmt.Sprintf("cp -r %s %s", clientfileSrc, clientfileDest)
   115  			_, err = utils.RunSimpleCmd(nydusdCpCmd)
   116  			if err != nil {
   117  				return fmt.Errorf("cp nydusdclinetfile failed %v", err)
   118  			}
   119  		}
   120  	}
   121  	startNydusdServer := fmt.Sprintf("cd %s && chmod +x serverstart.sh && ./serverstart.sh -d %s -i %s", nydusdserverDir, dirlist, localIP)
   122  	//convert image and start nydusd http server
   123  	_, err = utils.RunSimpleCmd(startNydusdServer)
   124  	if err != nil {
   125  		return fmt.Errorf("nydusdserver start fail %v", err)
   126  	}
   127  	logger.Info("nydus images converted and nydusd http server started")
   128  
   129  	eg, _ := errgroup.WithContext(context.Background())
   130  	for _, IP := range ipList {
   131  		ip := IP
   132  		eg.Go(func() error {
   133  			src := platform.GetMountCloudImagePlatformDir(cluster.Name, clusterPlatform[ip])
   134  			src = filepath.Join(nydusdFileDir, filepath.Base(src))
   135  			sshClient, err := ssh.GetHostSSHClient(ip, cluster)
   136  			if err != nil {
   137  				return fmt.Errorf("get host ssh client failed %v", err)
   138  			}
   139  			err = copyFiles(sshClient, ip, src, nydusdDir)
   140  			if err != nil {
   141  				return fmt.Errorf("scp nydusd failed %v", err)
   142  			}
   143  			if initFlag {
   144  				err = sshClient.CmdAsync(ip, envProcessor.WrapperShell(ip, nydusdInitCmd))
   145  				if err != nil {
   146  					return fmt.Errorf("init nydusd failed %v", err)
   147  				}
   148  				err = sshClient.CmdAsync(ip, envProcessor.WrapperShell(ip, initCmd))
   149  				if err != nil {
   150  					return fmt.Errorf("exec init.sh failed %v", err)
   151  				}
   152  				err = sshClient.CmdAsync(ip, envProcessor.WrapperShell(ip, cleanCmd))
   153  				if err != nil {
   154  					return fmt.Errorf("echo nydusdcleancmd to clean.sh failed %v", err)
   155  				}
   156  			}
   157  			return err
   158  		})
   159  	}
   160  	if err = eg.Wait(); err != nil {
   161  		return err
   162  	}
   163  	if !utils.InList(config.IP, ipList) {
   164  		return nil
   165  	}
   166  	return nil
   167  }
   168  
   169  func NewNydusFileSystem() (Interface, error) {
   170  	return &nydusFileSystem{}, nil
   171  }